On Fri, 2008-10-31 at 09:44 -0700, budden wrote:
> All this disappointment stems from experience with real system called
> Symbolicweb. I took a small part in its development (testing, etc).
> Someday I decided that it would be fine to have examples running not
> in a :symbolicweb package. In fact, final user will not work
> in :symbolicweb package. He would use it. Moreover, in context of web
> development, Symbolicweb can itself be considered as a library. So, if
> we give an example we would give a defpackage example too. I get much
> trouble with it.
Hum, I decided to give it a go;
http://common-lisp.net/~lnostdal/programming/lisp/symbolicweb/symbolicweb-examples.asd
http://common-lisp.net/~lnostdal/programming/lisp/symbolicweb/examples/package.lisp
http://common-lisp.net/~lnostdal/programming/lisp/symbolicweb/examples/chat.lisp
..I haven't followed this discussion but I know I'm doing a couple of
dumb things in SW wrt. symbols and exporting (and, yeah, other
things(#1)), so maybe that's why you're having trouble.
If you could describe what you're trying to use/do (packages etc.) and
what causes conflicts I can maybe make some changes to SW to make things
a bit easier.
..just a note to let you know; I don't have anything to add to the
discussion/topic besides this(#2). Might be a good idea to continue this
part of the discussion on the mailinglist
( ···········@googlegroups.com ) though.
#1: Development started in April. It has been driven by lack of time (I
can't get shit done in PHP at all..heh) and real world needs from the
start, so a lot of stuff has been rushed and still is ...
#2: While packages and conflicts can be annoying to deal with, I haven't
had to do huge amounts of manual work.
Hi Lars,
Problem is not with Symbolicweb itself. Most of the problems arose
from my attempt to use iterate in Symbolicweb.
I'm afraid what I say might lead to a LOTS of flame, but the problems
are multiple:
- poor design of standard loop, so one would want iterate instead;
E.g., Iterate allows to iterate on sql datasets, systems, children of
sw:container or whatever you want; All you need is to write a driver
consisting of several lines.
- iterate is not ideal too due to that symbol problems. In fact, it
needs redesign to allow keywords to be used for denoting clauses. But
this is not that easy as symbols are used in a special way in an
Iterate. Anyway, suppose I'll make a patch to iterate. Who would use
it? I'll need to promote it and the community says all is ok in the
current state of a lisp (well, it is possible to do things on lisp, in
this sence it is really ok);
- no standard library in lisp (compare that to STL/Boost or to Java
libraries). Anyone tries to add things that are apparently missing
from standard or fix those that are apparently ugly. So there are
multiple loop constructs, for, collecting, etc. When real-world open-
source application is being developed, each new developer comes with
its own habits and tries to import utilities which he find most
useful. It was iterate in my case but might be someone else and
something else. As an other example, I can note that there are at
least two incompatible popular variants of 'with-gensyms over the web.
One is that you use and another is from cllib (yours is better).
- package system is a complete mess (I insist on that whatever true
lispers say)
- every independent expert would say very definitely that a.b.c is
much easier to read that (c-of (b-of a)). Don't even say about (slot-
value (slot-value a 'b) 'c). I showed my lisp sources printed to my
girl-friend (she is a linguist) and I was unable to explain why eight
closing parens go in a row... It was a luck she didn't ask :) Parens
_are__there_ . One might filter them out at "high level" of brain's
OCR/text parser, but eye keep working upon it and neurons get
overheated occasionally... Real lisper's never notice that as there is
a special "sleep" function in a brain which simply turns your mind off
every time your eyes stumble against unnecessary nesting levels with
let/flet/macrolet or (c-of ...). It can be verified in a strict, clear
scientific experiment, but it is so evident that it needs no proof at
all. I know this is one of lisper's dogmas that parens are not there
and syntax does not matter. But (unfortunately for me) I can't
convince myself on that despite all my lisp experience.
Additionally I was disappointed when you told me about parenscript. MP
with code generation from a lisp is an area of my strategic interests
and if the author of parenscript is disappointed with it, it is a
shock for me. Of course, one reason can be easily seen from the same
a.b.c problem: javascript is just much shorter and easier to read. Add
here a possibility to quote strings with either single or double
quotes and... lisp loses despite defmacro (don't forget javaScript has
some MP abilities too).
Finally, I began to think that lisp is NOT a language for a web
development. It might work well as an MP tool or as a server platform,
but some more convinient syntax should be exposed to application
developer. It would be ideally if it could combine adequate syntax
with elegance of AST management and other successful design choices
unique to lisp. Something like Nemerle or even shell. I think such a
language is not too hard to develop using lisp as a platform, and I
have already started some prototype.
What goes to symbolicweb, I think you might want to add some
"symbolicweb-dsl" package, which would reexports most popular symbols
from :sw, :tbnl, :cl-who, etc... And tell a users to use that
symbolicweb-dsl. In fact, when you are combining new system from
several smaller ones, you definitely need to specify how it is
composed for potential users.
Sorry, there are many offtopics...
On Fri, 31 Oct 2008 11:37:19 -0700, budden wrote:
> - every independent expert would say very definitely that a.b.c is much
> easier to read that (c-of (b-of a)). Don't even say about (slot- value
Great! How should I write
(defun analyze-statistic (statistics &option (type 'total))
(let* ((statistic (slot-value statistics type)
(a (calculate-a statistic))
(b (calculate-b statistic)))
;; ...
))
(analyze-statistic *statistics*)
(analyze-statistic *statistics* 'unemployed)
(analyze-statistic *statistics* 'employed)
in the wonderful notation your "independent experts" have cooked up?
> (slot-value a 'b) 'c). I showed my lisp sources printed to my
> girl-friend (she is a linguist) and I was unable to explain why eight
> closing parens go in a row... It was a luck she didn't ask :) Parens
Then perhaps she should not be programming Lisp or designing computer
languages (which is not what linguists do anyway; if she dated smarter
people they wouldn't ask her about such things, but perhaps you have some
other redeeming quality).
> _are__there_ . One might filter them out at "high level" of brain's
> OCR/text parser, but eye keep working upon it and neurons get overheated
> occasionally... Real lisper's never notice that as there is a special
Luckily, you seem to have ample amounts of air between your neurons so
they will cool off.
Hint: you have just got started with CL, and you are trying to redesign
it. Quite a few people fall into this trap. None of them really succeed
in anything but the demonstration that they are not willing to devote
time to understanding the engineering decisions behind Lisp.
Before you share another one of your great suggestions, please program in
CL seriously for at least 3 months so you will learn the language as it
is.
HTH,
Tamas
Again. No. I didn't just started. This is a list with some of my
_lisp_ projects which I made for 9 years.
1. Delphi VCL to CL mappings via SWIG and FFC. Not finished (failed to
translate windows.h). What was implemented: Delphi VCL events handled
by lisp, lisp exception handlers for Delphi exceptions, C++ pointers
to lisp values. Garbage collection support for C++ objects which are
registered to be owned by lisp. That is, delete is invoked on C++ side
when lisp delegate of that C++ object is about to become a garbage
(had fun)
2. Multi-threaded oven control. One thread reads from thermometer,
second does strategy and prints info, third controls heater, fourth
accepts user commands (had fun)
3. Wind power station modeling (tiny DSL). Parsing of meteo archives
and calculating misc stats upon all system including modeling of
current accumulator battery charge (had fun)
4. SQL metadata generation for reports (earned some money)
5. C++ code generation for making Qt/Firebird database application
(earned some money)
6. DSL for describing dictionaries of SQL tables with attributes used
in UI generator (earned some money)
7. Tiny library for generating other languages from lexical trees
(helped a neighbour to make a web site)
Currently I am working under rather simple task: replace TADODataset
to TexADODataset in a Delphi app (lexical analysys of .pas and .dfm
and accurate replacement of words, parsing "uses" statements and
replacing lists of units used. Would earn some money.
Is it enough or I should work 3 months more?
(BTW, I'm looking for a lisp job all the time, but unable to find one.
Feel free to contact).
> (defun analyze-statistic (statistics &option (type 'total))
> (let* ((statistic (slot-value statistics type) ;;
First of all, you don't need to make this a slot. OO engine is
mistified, but it is very simple in its basic principle. Just arrays
with a named slots. Well for lisp they are hashes. You may use just an
array - it is exactly the same in terms of performance. E.g., in
Delphi this would be like this (don't remember exact syntax of
pointers etc).
type PVariant = ^variant;
type slot_names = (unemployed, employed, total);
type statistics = record
lispy_slots : array[statistics_type] of variant;
function slot_value(slot_name:statistics);
end;
function
statistics.slot_value(obj:statistics;slot_name:statistics):Pvariant;
begin
········@(obj.lispy_slots[slot_name]);
end;
You asked me about notation, not about language. JavaScript solution
would be much simplier and more straightforward as javascript has
getAttribute function or something like this. Of course, there may be
a lispy language with infix notation.
function analyze_statistic (statistics, optional [ type = total ] ) {
var statistic = statistics.getAttribute(type);
var a = calculate-a(statistic);
var b = calculate-b(statistic);
} // it is almost a javaScript
Well, I admit that lisp is rather fast and very flexible. And, of
course, it outperforms python, perl, etc... As fast as Java, but much
more dynamic. But we're talking about notation, not about runtime/
compiler.
> Now a new version of both A and B comes out. It so happens that A:FOO is
removed from A (or no longer exported), and at the same time,
a new symbol B:FOO appears in B, also naming a function.
No, I didn't overlook it. But this event is rather improbable. If so,
it is likely that A:FOO and B:FOO would differ in their arguments and
compiler would note that. If they are likely in argments and program
won't fail on (the ) checks, but would work incorrectly... well, this
is just not a lucky day... See what I wrote before about Delphi app
I'm currently working with. It would be a great pain to manage
windows.pas exports manually...
Oh, how I'm tired. Mixed everything. Pascal example would read as:
type PVariant = ^variant;
type statistics_slot_names = (unemployed, employed, total);
type statistics = record
lispy_slots : array[statistics_slot_names] of pvariant;
function slot_value(slot_name:statistics_slot_names); { returns a
pointer to slot }
end;
function
statistics.slot_value(slot_name:statistics_slot_names):Pvariant;
begin result:=lispy_slots[slot_name]; end;
If you use OO features, you might make the function virtual. Or you
make this function
dispatched via a dispatch table. Anyway, nothing unique. What makes
lisp powerful is:
1. GC (= safety)
2. defmacro, eval-when (= extensible compiler)
3. Native code compilation at runtime
Not an s-expressions.
budden <········@mtu-net.ru> writes:
> If you use OO features, you might make the function virtual. Or you
> make this function dispatched via a dispatch table. Anyway, nothing
> unique.
Wrong. CLOS is something (quite) unique, because it supports multiple
dispatch. With this the a.b.c syntax just don't make sense.
> What makes lisp powerful is:
> 1. GC (= safety)
> 2. defmacro, eval-when (= extensible compiler)
> 3. Native code compilation at runtime
> Not an s-expressions.
Hmmm... take a look at Boo or Dylan and compare those macro systems to
the ease of defmacro. Defmacro is powerful only because of
S-expressions! They are really important (and besides, I find lisp
syntax much easier to my eyes that Algol-like syntax; I find
S-expressions just beautiful).
Your problem is, that you look only at isolated features. But they are
not isolated, it's a really complex web. If you change something at
one point, the whole web will be changed, you will get quite a
different language.
--
Stefan.
Hi group!
Ok. Everyone seeks what is wrong with _me_. Thank your for you
diagnostics. Well. Let us now admit as an axiom: a I'm a stupid lamer.
Yes. I agree. I think now we might turn back to the topic.
Consider small example of how cl acts and how it would act if my
proposal were accepted.
Back to the beginning:
(defpackage :p1 (:export :sym :sym1))
(defpackage :p2 (:export :sym :sym2))
(defpackage :p3 (:use :p1 :p2)) ; package error p1:sym clashes with
p2:sym
Pascal Constanza suggests:
(defpackage :p3 (:use :p1 :p2) (:shadow :sym))
Ok, this works.
But now
> (do-symbols (s :p3) (print s))
P3::SYM
P1:SYM1
P2:SYM2
NIL
Hmm... Why do we need p3::sym? Only to avoid symbol clash. In fact we
will do (in-package :p3) and would only write either p1:sym and
p2:sym.
Where we get problems now?
1. auto-completion. We spent a whole day fixing p1 package. We get
acquanted that sym is just sym, not p1:sym. Then we switched to p3. In
a rush we type sy C-M-I and... p3::sym (which is unbound) goes to
code. We are lucky if we use it as a function or a global variable -
compiler would warn. What if (setf (gethash 'sym ...) ...)? We
introduced
a possibly serious and hard-to-find bug to our code. Cl suggested no
help to protect ourselfes from that bug. Where are you, safety
advocates?
2. (apropos "sym" :p3)
P2:SYM2
P1:SYM1
P3::SYM
Is it clear we just have a junk in our package? Why do we have it?
Because CL package system is ugly.
Ok. Let's give a good piece of shit about Kaz Kylheku opinion (oh, is
my English correct?) and export symbols one by one. This does work
too. Though we need to manually redistribute every new symbol to any
place where it intended to be is used. Ok, this is a Lisp, great
metaprogramming and symbolic computation language which might juggle
billion symbols per seconds. But... for you safety, you need sometimes
to do it manually... Sorry...
(delete-package :p3)
(defpackage :p3 (:use) (:import-from :p1 :sym1) (:import-
from :p2 :sym2))
(recompile-all-and-everything)
Well. Now
> (do-symbols (s :p3) (print s))
P1:SYM1
P2:SYM2
NIL
Hurray! We get rid of junky symbol.
Again. We get to :p1 and spent a whole day fixing a bug in it. We get
acquantied
that sym is written w/o prefix. Next we switch to :p3 and write
just "sym" by omission in :p3.
Lisp reader interns sym to :p3 and we get
> (do-symbols (s :p3) (print s))
P1:SYM1
P2:SYM2
P3::SYM
NIL
Why is it so? Yes, yes, it is because I am not only a lamer, I am a
tired lamer. I should have been careful and never use this symbol w/o
qualifier. And I did. I think, yes, I am a lamer. But partly it is
because a COMMON LISP PACKAGE SYSTEM IS A MESS. CL provokes me to err
here and I do.
... finding a bug in a hash...
Ouch!
> (unintern 'sym)
> (clean-and-recompile-all)
And this is not the all fun we get. Usually we'll
(defpackage :p3 (:use :cl) ...)
How fine it now becomes to use (apropos :sym :p3). It looks not only
"own" symbols of :p3
but symbols from :cl too. So we get tons of a junk. It is a mess.
Things should be ok if it looked only for such symbols with that home
package, but CLHS says:
> If package is non-nil, only the symbols accessible in that package are searched;
Btw, Sbcl deviates from cl standard in that (and it is very kind on
Sbcl developers) and delivers us from junk. It looks only for symbols
with that home package.
So. What ugliness there are?
1. When we use-packages, we need to shadow syms and get junky syms in
package, apropos, do-symbols.
2. When we import, we need to import every single symbol and again we
have no protection from junky symbols
3. There are too many symbols in our package: all imported and used
symbols present.
Now consider what would occur if we just
(in-packages :p3 :p1 :p2) ; as I described
(do-symbols (s :p3) (print s))
nil
No junk! No single symbol in :p3, though you may write sym1 and sym2 w/
o prefix.
(apropos "sym" :p1)
NIL
New version of apropos would be required, some kind of
(apropos-current-context "sym")
which looks for symbol in p1, p2, p3
This won't ever return junk from cl package, as neither package use
cl.
We get less apparent symbols at our system when we iterate over all
symbols, as no symbol references are copied from package to package.
And, next, we spent all day fixing p1 and get acquainted that sym is
used w/o prefix.
Next we switcth to p3 and write "sym" by omission.
Oops!!!!
Read error!
Lisp (would) protect us from creating a junky symbol.
Again and again I tell: there are other languages, e.g. Pascal, which
does not
report symbol clashes at all, uses priority instead of that. I do not
say it is good. The policy I suggest is much more strict than that of
Pascal. But even a Pascalish approach
is scalable enough. You may have a program with hundreds and thousands
of units. Each unit defines its own namespace, and dozens of those are
merged in every "uses" clause. In fact such a programs not only exist,
they are workable and they're working fine. I agree that importing
symbols one-by-one is a policy which would worth considering. But it
would be completely workable only if we could protect ourselfes
against introducing junky symbols to packages just by means of lisp
reader. In fact, we cannot do that even in sbcl. Sbcl allows us either
to open the package or lock it completely. If package is not locked,
we can at any time write:
'any-package::any-symbol
This is a mess and a very serious security and safety threat.
For qualifier approach to be really safe, we would need at least
(defpackage :p3 (:disallow :sym)) which says that "sym" name is locked
and it is impossible to intern sym to p3. Otherwise, use of qualifiers
makes code just more readable, but it in no means makes coding more
safe.
What do I think about those of you who criticise my suggestion? I
think you know internally that all this package system is a mess. You
just acquainted to that mess,
no more. You love lisp. Do you prefer to spend your life with lisp in
a mess or try
to make it clear?
And yes, I can design a better one - no design is needed, just fixing
an evident flaw is needed. In fact, what I suggested seem to be
enough. If you would spent less time debugging me, and spent more time
debugging what I suggest, may be we would find some pitfalls in what I
suggest.
Anyway, it is evident now that this would not be a breaking change,
only an extension. If you won't use (in-packages ) construct, all your
programs would run as good (or as bad) as they were running before. No
change to style, habits. No limitations. No additional danger.
I'll give you a time to read and react to this and then answer to the
rest of your posts.
On Fri, 31 Oct 2008 13:51:30 -0700, budden wrote:
> Currently I am working under rather simple task: replace TADODataset to
> TexADODataset in a Delphi app (lexical analysys of .pas and .dfm and
> accurate replacement of words, parsing "uses" statements and replacing
> lists of units used. Would earn some money.
>
> Is it enough or I should work 3 months more?
No, apparently you didn't gain anything in the past, so it is not likely
to happen. The other day we had someone who claimed he has been learning
Lisp for 3 years but it didn't show.
> (BTW, I'm looking for a lisp job all the time, but unable to find one.
I wonder why. With the great language design skills you have
demonstrated here, employees should be bidding for you like crazy.
>> (defun analyze-statistic (statistics &option (type 'total))
>> (let* ((statistic (slot-value statistics type) ;;
>
> First of all, you don't need to make this a slot. OO engine is
> mistified, but it is very simple in its basic principle. Just arrays
> with a named slots. Well for lisp they are hashes. You may use just an
> array - it is exactly the same in terms of performance. E.g., in Delphi
You are missing the point. I care about performance, but I also care
about readability of my programs. Yes, I could reimplement objects with
hash tables, but I chose not to, because the language I am working in has
the ability to address slots even when they are not hardcoded, and I find
this convenient.
> course, it outperforms python, perl, etc... As fast as Java, but much
Give me a break. Java bytecode doesn't come close to a decent Lisp
compiler.
> removed from A (or no longer exported), and at the same time, a new
> symbol B:FOO appears in B, also naming a function. No, I didn't overlook
> it. But this event is rather improbable. If so, it is likely that A:FOO
How would you know what is improbable?
Your problem is a classical one: you are a Blub [1] programmer, so you
want Lisp to look/feel like Blub. You make clueless suggestions about
superficial features. I am not saying that Common Lisp cannot be
improved, but it is ever improved, it will not be done by those who make
trivial syntactic modifications that would make crucial language features
(like macros) harder if not impossible and the whole language
inconsistent.
Tamas
[1] http://www.paulgraham.com/avg.html
Well, I'm very tired. But your attacks are so appealing... I like
debates.
> I wonder why. With the great language design skills you have
> demonstrated here, employees should be bidding for you like crazy.
Hmm, you may start just now. I didn't advertise myself last several
years I had enough money. Now it changed. BTW, I'm not a language
designer. DSL's are not languages. Writing a lisp macros is mainly too
easy to call it language design.
> You are missing the point.
I only answered to your question in a detail. Your question were to
easy. I could ask much more hard one. To be serious, in fact, Pascal
is of course not as flexible as lisp. But in the context your
question, difference is not so significant.
> Give me a break. Java bytecode doesn't come close to a decent Lisp
> compiler.
Do you know about JIT? You may find some data here. It is a surprise,
but Java on Linux is even a bit faster than SBCL. Yes, SBCL with all
types declared.
http://shootout.alioth.debian.org/u32q/benchmark.php?test=all&lang=java&lang2=sbcl
You can see competition rules are fair. You may even participate in a
competition. I tried to improve a couple lisp examples, but failed to
do that.
> How would you know what is improbable?
I'm a qualified mathematician. I graduated probability cathedra of
Mathematics and Mechanics department of MSU at 1995. I didn't use
mathematics a lot after that, but I still remember that probabilities
sometimes multiply :)
> Your problem is a classical one: you are a Blub [1] programmer, so you
> want Lisp to look/feel like Blub.
Your problem is that you are making too hasty conslusions.
Here is my code that I wrote today. Sorry, I won't translate comments
from Russian for you.
(eval-when (:compile-toplevel :execute) ; compiler only
(defpackage :tokenizer
(:nicknames :tkn)
(:use :cl :cl-ppcre :port :iter)
(:import-from :cl-user :let1 :match :withgensyms :ignored :map-
dir)))
(in-package :tokenizer)
(defparameter *repl-kind* #+ignore :clipboard "D:/sw/
conds.pas") ; :variable - ÐÅÒÅÍÅÎÎÁÑ, :clipboard - ÂÕÆÅÒ ÏÂÍÅÎÁ (ÎÅ
×ÓÅÇÄÁ ÒÁÂÏÔÁÅÔ ÉÚ-ÚÁ ÕÎÉËÏÄÁ), ÉÍÑ-ÆÁÊÌÁ (×Ù×ÏÄÉÍ × ÔÁËÏÅ ÖÅ . out)
(defvar *src-1*)
(cond ((eq *repl-kind* :variable)
(setf *src-1* (list "my pascal code")))
((eq *repl-kind* :clipboard)
(setf *src-1* (list (CAPI-WIN32-LIB::GET-CLIPBOARD-TEXT))))
(t (setf *src-1* (list (cl-user::read-file-into-string *repl-
kind*)))))
(defparameter *lexer-list* '(
(identifier (:sequence (:flags :case-insensitive-p) (:sequence
(:regex "[a-zA-Z_][a-zA-Z_0-9]*"))))
(reg-identifier (:register identifier))
(whitespace (:greedy-repetition 0 nil :whitespace-char-class))
(reg-whitespace (:register whitespace))
))
(loop for (a b) in
*lexer-list*
do (eval `(define-parse-tree-synonym ,a ,b)))
; classes are #\a - ident, #\n - number #\ -whitespace no eol #\1 {} #
\2 (* *) #\3 //...:eol #\h hex
(defstruct (token (:conc-name tok.)) class position text)
(defvar *print-tok-mode* :short ":short - ÔÏÌØËÏ ÓÏÄÅÒÖÉÍÏÅ É ËÌÁÓÓ
ÎÅÞÉÔÁÅÍÏ, :full - ËÁË ÏÂÙÞÎÏ")
(defmethod print-object ((tok token) stream)
(if (eq *print-tok-mode* :short)
(print-unreadable-object (tok stream :type nil)
(let ((text (tok.text tok))
(class (tok.class tok)))
(if (and (= (length text) 1)
(elt text 0) class)
(format stream "~A" class)
(format stream "~A ~A" class text))))
(call-next-method)))
(defmacro with-scan (scanner &body body)
"for use in tokenize. óËÁÎÉÒÕÅÔ ÓËÁÎÅÒÏÍ, Ó×ÑÚÙ×ÁÅÔ ÐÅÒÅÍÅÎÎÙÅ beg,
end, len É ×ÙÐÏÌÎÑÅÔ body × progn. Body ÍÏÖÅÔ ÍÅÎÑÔØ end É class
(class ÐÏ ÕÍÏÌÞÁÎÉÀ ÒÁ×ÅÎ ch, Ô.Å., ÜÌÅÍÅÎÔÕ ÓÔÒÏËÉ × ÐÏÚÉÃÉÉ start.
óËÁÎÅÒ, ÅÓÌÉ ÏÎ ÞÔÏ-ÔÏ ÎÁÈÏÄÉÔ, ÄÏÌÖÅÎ ÎÁÈÏÄÉÔØ ÜÔÏ ÏÔ ÎÁÞÁÌÁ ÓÔÒÏËÉ
(beg=start).
åÓÌÉ body ×ÅÒÎÕÌÏ t, ÓÞÉÔÁÅÍ, ÞÔÏ body ×ÙÑ×ÉÌÏ ÔÏËÅÎ ÏÔ start ÄÏ end.
ëÌÁÄ£Í ÅÇÏ × tokens. CÍÅÝÁÅÍ start ÎÁ ÜÌ-Ô ÐÏÓÌÅ end. åÓÌÉ ÖÅ body
×ÅÒÎÕÌ nil ÉÌÉ ÅÓÌÉ scanner ÎÉÞÅÇÏ ÎÅ ÎÁÛÅÌ, ÎÉÞÅÇÏ ÎÅ ÄÅÌÁÅÍ É
×ÏÚ×ÒÁÝÁÅÍ nil"
(withgensyms
(beg res)
`(multiple-value-bind
(,beg end junk1 junk2)
(scan ,scanner s :start start)
(declare (ignore junk1 junk2))
(when ,beg
(assert (= ,beg start))
(let* ((class ch)
(len (- end ,beg))
(,res (progn ,@body)))
(ignored len)
(when ,res
(push (make-token :class class
:position start
:text (subseq s start end)) tokens)
(setf start end)
t))))))
(defmacro mk-token-from-ch ()
"äÌÑ tokenize. äÅÌÁÅÔ ÔÅËÕÝÉÊ ch ÔÏËÅÎÏÍ Ó ÔÁËÉÍ ÖÅ ËÌÁÓÓÏÍ"
`(progn (push (make-token :class ch :position start :text (subseq s
start (+ start 1)))
tokens)
(incf start)))
(defun tokenize (s &key (start 0))
"×ÏÚ×ÒÁÝÁÅÔ Ä×Á ÚÎÁÞÅÎÉÑ - ÓÐÉÓÏË ÔÏËÅÎÏ× É ÉÎÄÅËÓ, ÎÁÞÉÎÁÑ Ó
ËÏÔÏÒÏÇÏ ÎÕÖÎÏ ÉÓËÁÔØ ÄÁÌØÛÅ"
(let (tokens ch prev-start
(ident-scanner (create-scanner '(:sequence :modeless-start-
anchor identifier)))
(num-scanner (create-scanner "\\A\\-*[0-9]+(\\.([0-9]*))*(e-
*[0-9]+)*")) ; seem to be ok for all reals
(hex-num-scanner (create-scanner "\\A\\$[0-9]+"))
(whitespace-no-eol-scanner (create-scanner
'(:sequence :modeless-start-anchor
(:greedy-
repetition 1 nil (:alternation #\ #\Tab)))))
(comment-1-scanner
(create-scanner '(:sequence :modeless-start-anchor #\
{ (:greedy-repetition 0 nil (:inverted-char-class #\})) #\})
))
(comment-2-scanner
(create-scanner '(:sequence :modeless-start-anchor #\( #\*
(:non-greedy-repetition 0 nil :everything) #\* #\))))
(comment-3-scanner
(create-scanner '(:sequence :modeless-start-anchor #\/ #\/
(:non-greedy-repetition 0 nil :everything) :end-anchor) :multi-line-
mode t))
)
(loop
(setf prev-start start)
; (print start)
(when (>= start (length s)) (return-from tokenize (nreverse
tokens)))
(setf ch (elt s start))
(cond
((alpha-char-p ch) (with-scan ident-scanner (setf class #\a)))
((or (digit-char-p ch)
(eql #\. ch)
(eql #\- ch))
(or
(with-scan num-scanner (setf class #\n))
(mk-token-from-ch))
)
((member ch '(#\ #\Tab)) (with-scan whitespace-no-eol-scanner
(setf class #\ )))
(t
(case ch
(#\$ (with-scan hex-num-scanner (unless (= len 1) (setf class
#\h))))
(#\{ (or (with-scan comment-1-scanner (setf class #\1))
(mk-token-from-ch)))
(#\( (with-scan comment-2-scanner (unless (= len 1)) (setf
class #\2))
(mk-token-from-ch))
(#\/ (or (with-scan comment-3-scanner (setf class #\3))
(mk-token-from-ch)))
(#\' (macrolet ((shift ()
'(progn
(incf end)
(when (= end (length s))
(go :failed))
(setf chh (elt s end)))))
(prog (chh (end start))
:beg-loop
(shift)
(setf chh (elt s end))
(when (eql chh #\') (go :got-a-quote))
(go :beg-loop)
:got-a-quote
(shift)
(when (eql chh #\') (go :beg-loop)) ; ÎÅ ÐÁÒÓÉÍ
ÓÔÒÏËÕ, Á ÓÔÏÉÌÏ ÂÙ...
:closed
(make-token :class #\'
:position start
:text (subseq s start end))
(setf start end)
(return)
:failed
(mk-token-from-ch))))
(t (mk-token-from-ch)))))
(assert (> start prev-start)))))
(defun skip-comments-and-whitespace (token-list)
(loop for tok in token-list
for class = (tok.class tok)
unless (member class '(#\ #\1 #\2 #\3))
collect tok))
(defun split-list-by-condition (fun list-ptr)
"òÁÚÂÉ×ÁÅÔ list × ÔÏÞËÅ, ÇÄÅ fun ÐÅÒ×ÙÊ ÒÁÚ ÒÁ×ÎÏ true. list-ptr -
ÜÔÏ cons, cdr ËÏÔÏÒÏÇÏ ÓÏÄÅÒÖÉÔ list.
õ list-ptr ÏÔÒÅÚÁÅÔÓÑ ×Ó£, ÎÁÞÉÎÁÑ Ó ÔÏÞËÉ, ÇÄÅ fun = true, É
×ÏÚ×ÒÁÝÁÅÔÓÑ. Last ÏÓÔÁÔËÁ list-ptr ×ÏÚ×ÒÁÝÁÅÔÓÑ
× ËÁÞÅÓÔ×Å ×ÔÏÒÏÇÏ ÚÎÁÞÅÎÉÑ. åÓÌÉ fun ÎÅ ÓÔÁÌÏ ÉÓÔÉÎÏÊ, ×ÏÚ×ÒÁÝÁÀÔÓÑ
Ä×Á ÚÎÁÞÅÎÉÑ nil"
(loop
:for old-sublist :on list-ptr
:for sublist :on (cdr list-ptr)
:for it := (car sublist)
:when (funcall fun it)
:do (progn
(setf (cdr old-sublist) nil)
(return (values sublist old-sublist)))
:finally (values nil nil)))
#| (defun wind-use-lists (tokens)
(multiple-value-bind
(loop
with state = :initial
for tok in tokens
for class = (tok.class tok)
for text = (tok.text tok)
|#
(defparameter *tokens* (tokenize (car *src-1*)))
(defparameter *tokens-w-o-namespace* (skip-comments-and-whitespace
*tokens*))
(defvar *interface-uses* nil)
(defvar *implementation-uses* nil)
(defvar *implementation-uses-start* nil "ÜÔÏ ÂÕÄÅÔ ÕËÁÚÁÔÅÌØ ÎÁ ÔÏËÅÎ
uses × implementation")
(defvar *interface-uses-start* nil "ÜÔÏ ÂÕÄÅÔ ÕËÁÚÁÔÅÌØ ÎÁ ÔÏËÅÎ uses
× interface")
(defun note-uses (token-list-w-o-whitespace)
(loop for x in token-list-w-o-whitespace
for class = (tok.class x)
for text = (tok.text x)
with flag = nil with section = nil
when (and flag (eq class #\a) (eq section :interface)) collect text
into interface-uses
when (and flag (eq class #\a) (eq section :implementation)) collect
text into implementation-uses
when (and (eql class #\a) (equalp text "interface")) do (setf
section :interface)
when (and (eql class #\a) (equalp text "implementation")) do (setf
section :implementation)
when (and (eql class #\a) (equalp text "uses"))
do
(setf flag t)
(if (eq section :interface)
(setf *interface-uses-start* x)
(setf *implementation-uses-start* x))
when (eql class #\;) do (setf flag nil)
finally (setf *interface-uses* interface-uses *implementation-uses*
implementation-uses)))
(note-uses *tokens-w-o-namespace*)
(print *interface-uses*)
(print *implementation-uses*)
(defun sublist-starting-from-token (token token-list)
(let1 pos (position token token-list)
(assert pos)
(nthcdr pos token-list)))
#| (defun subst-ado-with-ex-ado ()
(let* ((ado-in-int (member "adodb" *interface-uses* :test 'equalp))
(ado-in-impl (member "adodb" *implementation-uses* :test
'equalp)))
(cond
(ado-in-int |#
(defun subst-bar-with-baz ()
(let* ((int-uses-list (sublist-starting-from-token *interface-uses-
start*
*tokens*)) (use-
foo-token (find "bar" int-uses-list :key #'tok.text :test #'equalp)))
(assert use-foo-token)
(setf (cdr int-uses-list)
(cllib:substitute-subseq (cdr int-uses-list)
(list use-foo-token)
(list (make-token :class #\a :text
"baz,quux"))
:test 'equal))))
(defun print-list-of-tokens (lst &optional (stream t))
(loop for x in lst
for text = (tok.text x)
do (format stream "~A" text)))
(defparameter *redo-once* nil)
(defun undo-repl () (prog1 (second *src-1*) (when (cdr *src-1*) (setf
*redo-once* (pop *src-1*)))))
(defun redo-repl () (unless *redo-once* (error "can't redo")) (push
*redo-once* *src-1*) (setf *redo-once* nil))
(defun a-word (word) `(:sequence whitespace :word-boundary ,word :word-
boundary whitespace))
budden <········@mtu-net.ru> writes:
> DSL's are not languages. Writing a lisp macros is mainly too easy to
> call it language design.
Just because DSL's may be easy to *implement* doesn't mean that they
are easy to *design*. Take for example GUIs. There are many
GUI-Designers out there today, so constructing some GUI is really
easy. But designing a good GUI, making it's use efficient and (in some
kind) intuitive (really bad word in this context, but that's another
debate), is really hard (and out there are tremendous amounts of
really bad designed GUIs, maybe exactly because they are so easy to
construct so most developer think "hey, it's so easy, it can't be
important and really thinking about good design is too hard and too
expensive").
Also designing programming languages is really hard. A language is not
just a pile of isolated features. Many really smart people worked hard
to design Common Lisp -- you yourself say you are no language
designer. Why do you think anybody should take you serious if you
critize anything in Common Lisp?
If you are so annyed, why don't you use another language? Maybe there
are some things to Common Lisp that you find helpful and important
that you don't find in other languages? Maybe these tools won't be in
Common Lisp if everything will be changed the way you wish? Common
Lisp is not Ruby, is not Python, is not Dylan, is not Java,.... Common
Lisp is Common Lisp. Period. It's that simple. Deal with it.
--
Stefan.
From: Kaz Kylheku
Subject: Re: Symbol clashes: how to avoid them. Part 2
Date:
Message-ID: <20081031140001.775@gmail.com>
On 2008-10-31, Tamas K Papp <······@gmail.com> wrote:
> On Fri, 31 Oct 2008 11:37:19 -0700, budden wrote:
>
>> - every independent expert would say very definitely that a.b.c is much
>> easier to read that (c-of (b-of a)). Don't even say about (slot- value
>
> Great! How should I write
>
> (defun analyze-statistic (statistics &option (type 'total))
> (let* ((statistic (slot-value statistics type)
> (a (calculate-a statistic))
> (b (calculate-b statistic)))
> ;; ...
> ))
>
> (analyze-statistic *statistics*)
> (analyze-statistic *statistics* 'unemployed)
> (analyze-statistic *statistics* 'employed)
>
> in the wonderful notation your "independent experts" have cooked up?
Why:
String slot_access = "statistics." + type.toString();
System.library.greenspun.functions_that_begin_with_e.eval(slot_access);
:)
Tamas K Papp wrote:
> Then perhaps she should not be programming Lisp or designing computer
> languages (which is not what linguists do anyway; if she dated
> smarter people they wouldn't ask her about such things, but perhaps
> you have some other redeeming quality).
> ...
> Luckily, you seem to have ample amounts of air between your neurons
> so they will cool off.
It's sad that c.l.l. has been taken over by users of CL.
It would be hard to find remarks as savage as this in
any other newsgroup.
budden wrote:
> - every independent expert would say very definitely that a.b.c is
> much easier to read that (c-of (b-of a)). Don't even say about (slot-
> value (slot-value a 'b) 'c). I showed my lisp sources printed to my
If you like the dot syntax, why don't you write a reader macro for it ?
Or maybe as an easier first step, a macro like this : (dots a b c).
Sacha
I don't know. Sometimes it seems that lisp still can be useful as an
end-user language it we fix at least the most ugly things. Readmacros
might confuse SLIME and lisp-mode. Now I have EMACS sources installed,
maybe all this can be fixed. Dots are fine, but CLOS is too
flexible... Using dots require a restrictions upon naming. Can be used
in my own (non-shared) code, but not in a team work.
One possible (and elegant) way to fix all this would to change dot to
colon. E.g.
a:b:c instead of a.b.c. This way, would be package~=class. But now we
get to the topic of current discussion - insufficient convinience of
package system. And there is package=file convention. So,again there
would be difficulties with SLIME for sub-packages (e.g. subpackages
would be useful for enums or private properties).
Anyway, implementing any cosmetic changes to lisp will make me lonely.
Lispers think lisp is ok, others don't want to learn setf, progn,
destructuring-bind, multiple-value-bind etc. Who will use that
language? Where is PLisp and other like effors? Nowhere.
On the other hand, any C-like language can be parsed to AST rather
easily (well, not C, but Java can, don't know about javaScript). It is
easy to add quasiquoting: just
DEFMACRO( foo (symbol) { quasiquote( { a = unqote(symbol); } ) }
Javascript is almost a lisp itself, it has &key parameters, closures
and all that.
So everything is very straightforward. AST can be presented in some
easily manageable form too (especially in garbage-collecting
languages). This language would be much more popular, especially if it
is made on powerful dynamic lisp platform.
From: Kaz Kylheku
Subject: Re: Symbol clashes: how to avoid them. Part 2
Date:
Message-ID: <20081031134708.996@gmail.com>
On 2008-10-31, budden <········@mtu-net.ru> wrote:
> - package system is a complete mess (I insist on that whatever true
> lispers say)
But you could design a better one, right?
Problem is, you obviously don't have a clue about how to look at a system from
all possible angles, identify all possible issues, filter out those that are
non-issues and prioritize the rest.
> - every independent expert would say very definitely that a.b.c is
> much easier to read that (c-of (b-of a)).
That's until the dot notation sprouts some hair, like for e-mail
routing:
·······@a.b.c!d
:)
> Don't even say about (slot-
> value (slot-value a 'b) 'c). I showed my lisp sources printed to my
> girl-friend (she is a linguist) and I was unable to explain why eight
> closing parens go in a row...
You're joking, right? Linguists learn about bracket notation in their
undergraduate classes, and such material is tested on exams.
E.g. ``rewrite this syntax tree using labelled brackets''.
> Finally, I began to think that lisp is NOT a language for a web
Blah blah blah. Who gives a shit about your opinions about
what Lisp is good for.
Kaz Kylheku wrote:
> Blah blah blah. Who gives a shit about your opinions about
> what Lisp is good for.
It's sad that c.l.l. has been taken over by users of CL.
It would be hard to find remarks as savage as this in
any other newsgroup.
On 1 Nov., 21:59, "William James" <·········@yahoo.com> wrote:
> Kaz Kylheku wrote:
> > Blah blah blah. Who gives a shit about your opinions about
> > what Lisp is good for.
>
> It's sad that c.l.l. has been taken over by users of CL.
> It would be hard to find remarks as savage as this in
> any other newsgroup.
I can't say that I'm impressed by your performance here either. All
you do is post negative remarks and trivial pieces of Ruby code in a
Lisp newsgroup.
As a contrast to your posts, I have tried to understand the problem of
the original poster and give some constructive answers (in another
thread). My impression is that the original poster (budden) had some
good questions.
William, it really doesn't show you in the best light making negative
remarks of comp.lang.lisp posters while most of your posts here
violate netiquette (see for example http://en.wikipedia.org/wiki/Netiquette
) by posting off-topic - things that belong to comp.lang.misc or
comp.lang.ruby, but not comp.lang.lisp . Your posts here can be safely
ignored, I have to say. I haven't got any useful information out of
your posts on comp.lang.lisp. Nothing that helps me with Lisp
programming. Your whining doesn't make it better.
From: Kaz Kylheku
Subject: Re: Symbol clashes: how to avoid them. Part 2
Date:
Message-ID: <20081102210249.299@gmail.com>
On 2008-11-01, William James <·········@yahoo.com> wrote:
> Kaz Kylheku wrote:
>
>> Blah blah blah. Who gives a shit about your opinions about
>> what Lisp is good for.
>
>
> It's sad that c.l.l. has been taken over by users of CL.
I just glossed through some comp.lang.lisp material from around 1989.
It leans heavily toward Common Lisp.
And that was probably before you were born.
Why don't you write up a statement of what you think is topical around here?
It will be entertaining to see how creatively you weave Ruby trolling into it.
Thanks, William
I am new to the group (not to the lisp) and I came here with a
sword in my hand, so I don't expect everyone would be friendly. And,
web is not very friendly place at all.
Of course, I don't say I like this. So thanks for the protection.
But I'd like to turn back to the topic. It would be fine if someone
would dare to agree to me that behaviour of CL I described should be
considered more to be more a "design flaw" than a "feature". And that
in fact safety is not an excuse for reporting clashes at merge-time:
safety is not achieved anyway.
There is an (rather ugly?) mostly-portable way to do what I want:
we would need to redefine #\|, #\\ and all constituent characters in a
readtable so that we could hook on process of reading a symbol (did I
miss smth?)
This would allow not only to modify a package system behavior in
any desired way, but also to assign read-time values/functions to
symbols. Hmmm... This would allow to read a.b.c as (dots a b c),
define (in-packages), introduce global synonyms and maybe many more...
Though this feature seem to be dangerous enough and maybe I cause more
flame by that, but it is a valid application of read-macros and it is
no more dangerous than read-macros themselves. If used instead of some
read-macros it would look much more lispy than that hackish ·@, #!
etc.
The price for that would be a bit slower reader.
Does anybody know if this feature is implemented by someone already?
budden <········@mtu-net.ru> writes:
> Thanks, William
> I am new to the group (not to the lisp) and I came here with a
> sword in my hand, so I don't expect everyone would be friendly. And,
> web is not very friendly place at all.
> Of course, I don't say I like this. So thanks for the protection.
> But I'd like to turn back to the topic. It would be fine if someone
> would dare to agree to me that behaviour of CL I described should be
> considered more to be more a "design flaw" than a "feature". And that
> in fact safety is not an excuse for reporting clashes at merge-time:
> safety is not achieved anyway.
> There is an (rather ugly?) mostly-portable way to do what I want:
> we would need to redefine #\|, #\\ and all constituent characters in a
> readtable so that we could hook on process of reading a symbol (did I
> miss smth?)
> This would allow not only to modify a package system behavior in
> any desired way, but also to assign read-time values/functions to
> symbols. Hmmm... This would allow to read a.b.c as (dots a b c),
> define (in-packages), introduce global synonyms and maybe many more...
> Though this feature seem to be dangerous enough and maybe I cause more
> flame by that, but it is a valid application of read-macros and it is
> no more dangerous than read-macros themselves. If used instead of some
> read-macros it would look much more lispy than that hackish ·@, #!
> etc.
> The price for that would be a bit slower reader.
>
> Does anybody know if this feature is implemented by someone already?
Not AFAIK.
But nothing prevents you to implement it. Either at a metalinguistic
level, or more easily since nowadays we have open source
implementations leaving you the freedom to do so, by modifying an
existing implementation. It shouldn't be too hard.
Be sure to report to us the results of your investigation, please.
--
__Pascal Bourguignon__
From: Kaz Kylheku
Subject: Re: Symbol clashes: how to avoid them. Part 2
Date:
Message-ID: <20081103151802.675@gmail.com>
On 2008-11-03, budden <········@mtu-net.ru> wrote:
> Thanks, William
> I am new to the group (not to the lisp) and I came here with a
> sword in my hand, so I don't expect everyone would be friendly. And,
> web is not very friendly place at all.
> Of course, I don't say I like this. So thanks for the protection.
> But I'd like to turn back to the topic. It would be fine if someone
> would dare to agree to me that behaviour of CL I described should be
> considered more to be more a "design flaw" than a "feature". And that
> in fact safety is not an excuse for reporting clashes at merge-time:
> safety is not achieved anyway.
> There is an (rather ugly?) mostly-portable way to do what I want:
> we would need to redefine #\|, #\\ and all constituent characters in a
> readtable so that we could hook on process of reading a symbol (did I
> miss smth?)
This is possible, and even highly portable and clean (i.e. effects confined to
the files which use this).
But I suspect you will never recover the development effort you put into this
(even if we include that of everyone who ends up using it).
You're solving something that is a complete non-problem in practice.
It might be a different story if Lisp programs were structured such that each
file had to use several packages and deal with conflicts.
But, I repeat myself, Lisp programs are written so that many modules share the
same package definition. If you have to resolve five conflicts in a DEFPACKAGE,
but that DEFPACKAGE is used by a hundred files, that's one hundred files in
which you don't have to deal with those five conflicts.
The single DEFPACKAGE improves the readability of the program, because it
centralizes the symbol resolution policy of one hundred files, and resolves it
in the same way for each of them. If packages FOO and BAR are used, and
conflict on symbol X, that defpackage will resolve the conflict, establishing
what unqualified X means. In those hundred files which use that same
DEFPACKAGE, unqualified X will mean exactly the same thing.
If you had to deal with this kind of thing in every single file, you would have
a point; maybe some hack at the reader level would bring about a net increase
in productivity.
And you obviously hadn't yet thought about the add/delete ambiguity among
namespaces. If you use a mechanism like Lisp's USE-PACKAGE, C++'s using
namespace or Ada's with, you are creating the possibility that a symbol
migrates from one package to another, creating a bug in the program.
I.e. today package FOO has symbol X, and package BAR does not. We use both of
them and there is no conflict on X; today, X means FOO:X. Tomorrow, we upgrade
to new versions of both packages their respective third parties. The symbol
FOO:X disappears, but now there is a BAR:X. There is still no conflict on X,
but now your unqualified X means BAR:X, which you didn't intend. No error is
detected.
It's the stupidity of USE-PACKAGE (and everything like it in any other
programming language).
USE-PACKAGE has the above problem if you just use one package!
Today we use package FOO which provides X. Unqualified X means FOO:X. Perhaps
we define a method on it: (defmethod x ...). Our intent is to add a method to
the generic function FOO:X. Tomorrow, the package changes so that FOO:X exists
no more. Our program still refers to the unqualified X, but now it's simply
interned into the local package. The defmethod still works, but the method goes
to the wrong generic function, and thus will never be called.
Such problems are prevented by using :SHADOWING-IMPORT-FROM in DEFPACKAGE, rather than :USE.
But instead you're working on making a blunt, error-prone tool more convenient
to use.
Hi Kaz, group
> I.e. today package FOO has symbol X, and package BAR does >not. We use both of
>them and there is no conflict on X; today, X means FOO:X. >Tomorrow, we upgrade
>to new versions of both packages their respective third >parties. The symbol
>FOO:X disappears, but now there is a BAR:X.
You have already written this before, and I have already replied that
such an event is very unlikely (has a very low probability). Lisp, as
a dynamically typed language, allows you to do other (more probable)
errors. So, in the shadow of other possible errors, event you describe
is not so significant. It is especially improbable that both symbols
would coincide in their usage (variable/function/type name) and
signature, so compiler would not note that.
I didn't mention one exception:the situation when we reorganize
structure of library with several packages and intentionnaly move a
symbol from one package to another. But in this case situation is
under control.
> Such problems are prevented by using :SHADOWING-IMPORT-FROM
> in DEFPACKAGE, rather than :USE.
If a coder forget which symbol is imported, he might err. Consider
safety as whole, not only the technical side (what language allow/
disallow), but a human factor too.
If you do, you'll see there is no way to avoid errors. There is a way
to lower the probability of those (compiler checks, assertions,
testing, higher level language constructs). But no way to avoid them
at all. So there is always a some tradeoff and also a style/habit/
tradition factor.
> But, I repeat myself, Lisp programs are written so
> that many modules share the same package definition
This is a unique feature of lisp programs. I used to write rather
large applications in Delphi and SQL, medium size applications in a C+
+. There are always many namespaces (not only "package" namespaces,
but those created implicitly by classes and sql tables).
Sometimes it is convinient to have large namespaces, sometimes it is
more convinient to make a program modular with many small namespaces
(preferrably, w/o write access). I'm sure the right choice depends on
a problem domain only, not on a programming language. OO is extreme -
it makes namespace too fragmented. But lisp is another exterme - it
makes namespaces too vast.
I'm sure (some) lisp programmers would sometime like their programs to
be modular, but it is hard to implement due to package systems
difficulties.
> But I suspect you will never recover the development effort you put into this
I think I spent more time here than is needed to implement that...
Though this was a design stage... I think it can work like this:
- make all constituent characters a macro characters
- reader function would do unread-char and then read symbol with
standard readtable, with *package* bound to (find-package :my-secret-
package)
Then, instead of returning, it would allow user hook to be run. The
hook might:
- intern the symbol to every package
- generate a error (a package lock)
- return a synonym instead of a symbol read (hm, it looks like the
symbol needs to be interned? Or not? synonyms might be bound to symbol-
name, or to symbol itself. It is a design choice or both can be
implemented, I don't know)
- do not intern a string ·······@comp.lang.lisp", but, instead, parse
it and return
#S(e-mail :user budden :domain (lisp lang comp)). And so on.
Am I wrong with design? Did I miss something?
Yes.
I am wrong as it is impossible to implement virtual packages (e.g.
hierarchical packages) this way. And,
a::b would be interned before a hook is called, so no way to implement
package locks in a portable way. It seems I need reimplement reading
symbol code and parse symbol name by myself. Is it too hard? I think
not.
Or maybe try to bind a handler on package-error? This looks ugly...
Have to take a look at it.
Btw, my job is stalled... Time to turn to it back.
I think making a read-time synonyms for symbols are not necessary. I
took a look at that code in sbcl's reader.lisp and found that can be
done fairly with #. syntax. In this case it is clearly seen that
symbol would expand at read-time.
Would be a fun to have "read-time symbol macro bindings". That is,
when reader reads the-fun in
(the-fun arg1 arg2), looks at a property 'read-time-function, and, if
it is bound to function,
calls that function which would read all the symbols up to the end of
the list and process them.
This can be done with (dispatch) macro characters, but it looks a bit
ugly and not a lispy.
E.g. now I get a rather simple and (hopefully) portable code which
reads a form in the scope of other
package:
#.#.<<with-package :iter 'defsynonym >>
would return iterate::defsynonym
From: Kaz Kylheku
Subject: Re: Symbol clashes: how to avoid them. Part 2
Date:
Message-ID: <20081107114407.573@gmail.com>
On 2008-11-04, budden <········@mtu-net.ru> wrote:
> Hi Kaz, group
>> I.e. today package FOO has symbol X, and package BAR does >not. We use both of
>>them and there is no conflict on X; today, X means FOO:X. >Tomorrow, we upgrade
>>to new versions of both packages their respective third >parties. The symbol
>>FOO:X disappears, but now there is a BAR:X.
>
> You have already written this before, and I have already replied that
> such an event is very unlikely (has a very low probability).
Can you quantify this probability as a concrete number between 0 and 1?
Hi Kaz, group!
Not the probability, but the rate (probability per added symbol) can
be calculated from the following initial data:
1. Structure of allowed signatures, including symbol name variance in
parameters (say, keyword). This gives us a number of
all distinct entities in a namespace. This number will be very large
(billions, at least).
2. Number of packages and a number of symbols currently in every
package
3. Rate of deletion relative to addition.
But it has ho sence. First, we're talking about tradeoff, so we
need to estimate relative risks. Absolute numbers would be useless.
What would you put on the other side? My point that it is a reduction
of readibility (in an extereme, all symbols are prefixed: maximum
safety, minimum readability). It is harder to read (and easier to
overlook a semantic error) in a code which is not compact. User can
forget, misprint or mix up a prefixes, which will lead just to the
same result. All this can hardly be estimated by a probability (maybe
by a statistics).
Also, it is evident for me that such an event is improbale. I
worked with Pascal and SQL for a rather long
time and only once I have heard about this kind of conflict. But I had
problems with importing in CL very often.
To add,
1. Symbols are rarely removed. They are deprecated instead.
2. Regression testing won't pass such an event. Testing is needed
anyway,
as function semantic might change without changing its name.
From: Kaz Kylheku
Subject: Re: Symbol clashes: how to avoid them. Part 2
Date:
Message-ID: <20081110150140.110@gmail.com>
On 2008-11-10, budden <········@mtu-net.ru> wrote:
> To add,
> 1. Symbols are rarely removed. They are deprecated instead.
That is false. A symbol is effectively removed whenever someone renames
something.
``Hmm, class FOO should have been called STICKY-FOO. <edit, edit, ...>''
Now FOO is gone.
And any engineer who is careful enough to put every renamed symbol through a
deprecation stage would certainly not be taking your side in this argument. :)
> 2. Regression testing won't pass such an event.
Pardon? Regression testing catches everything???
> So this is your number between 0 and 1?
Sorry, I got no time to caclculate this. I only showed how this can be
done. I'll guess (maybe incorrect) that rough estimation for a two
package case under a realistic conditions (symbol quantity is
relatively small, add and remove rates are relatively small) is
(number of added symbols in package A in the time passed from last
update)*(number of deleted symbols in package B passed from the last
update)/(number of potential identifiers). This is made in assumption
that symbols in package B are only removed, and symbol in package A
are only added and gives an estimation of a probability of that
conflict between versions. All complicates greatly under weaker
assumptions.
> Yes, the space of possible symbols is very large. Programmers do not
invent names by generating random strings that are lexically valid
identifiers.
I estimated this prior to writing :) Say, we get 5000 English words
(maybe even I know have learned that number of English words). Let
identifiers to be combined from up to two dash-delimited English words
and, possibly, with a suffix/prefix such as n or *. This gives us no
less than half a billion fair identifiers. All we now identifiers that
go beyond this. E.g. multiple-value-bind, prog1, symbol-macrolet.
> A symbol is effectively removed whenever someone renames something.
Good style of removing exported symbol in a published library is to
copy it and to make old name deprecated. Particularily, in a CL it can
be combined with unexporting a symbol, so "lib::old-name is not an
external symbol in lib" would occur upon a recompilation and give
developer a hint that something is wrong.
So, say, we added 20 symbols to A and removed 2 symbols from B.
Probability estimation is
20*2/500.000.000=8e-8. What next? How do you think, is it large or
small? Anyway, this can be estimated only in a relation to something
else.
We were talking only about a words now. But symbol in a programming
language is not only a name. It has attributes which very likely won't
coincide in foo:sym and bar:sym even if that kind of conflict would
appear. It would be more honest to take it into account too, but it is
too complicated. But let us suggest that there 50% are class names
(and not a functions) and the rest 50% are only functions and not a
classes. This about halfes a probability of a conflict as classes have
initargs, while function have args, their count and keyword names
would coincide very unlikely (no, I will not calculate this). If a
symbol names both class and a function, it is likely that their
definitions are related. E.g. function names a constructor of that
class.
> If you don't have the statistics, then you can't say something is improbable.
I have the statistics. I have an SQL application with 100 tables.
Every table has an "id" field. Half of tham have "name" field. I wrote
several thousand (maybe more several dozen thousand) queries joining
2,3,4,5,6 or more tables. Clashes are not a problem. Yes, sometimes I
had a problems with it, but this problem (write foo.id instead of
bar.id) is well known and it was always identified at debugging stage.
I've seen a Delphi application with 500 units. Every unit uses 10-20
other units, including "window.pas" unit. No problems with clashes.
All these are production commercial application with a long
maintainance cycle (5-8 years) which use external libraries, and were
built by several developers. That is more than enough for me. I can't
imagine 500 packages in a lisp application without using qualified
identifiers almost everywhere. Anyway, package system would be altered
in a large project, maybe using some other wrappers around
defpackage.
> The current understanding (correct it if it's wrong) is that you had problems
with indiscriminate package use (called symbol "inheriting" by ANSI
CL), not
with importing individual symbols.
Not only that. I don't want to repeat to that, I think I expressed my
point in an enough detail. The problem is that there are no lisp jobs.
I like lisp, but if I want to use it, I have be able to do things
quickly. Otherwise I simply won't be able to gain any profit from
lisp. I have no time for importing symbols one by one. It is a waste
of time, compared to the ease of "using packages" I have in Pascal and
SQL.
Moreover, the more packages I have, the greater the pain. Someday I
felt this is a serious obstacle to my development in a lisp. Working
for a current task in a rush, I tend to pile all symbols to one
package and I know this is a bad practice, but when I try to bring it
in an order, I face serious difficulties.
Finally, if I'll stay with lisp, I think I'll do that in-packages
thing and would use it for my own. Instead of doing that work, I spend
my time trying to convince you that flaws are really flaws and
convinience is no more dangerous that other dangers. How would this
effort return to me? Someone else would call me a nut. It is clear
already that lispers are rather conservative and most of them won't
accept any changes. But this is not required for me. It is better to
have a community, but if it hard to create such, ok, I'll do what I
want for myself.
I'm using only two lisp implementations for now. Lispworks uses both
intern and find-package in a reader, Sbcl is open source and I think
(declaim (notiline intern)) in the sources would help. I have already
implemented a "dots" macro, w/o SLIME though, it took just half an
hour. in-packages is a bit more complicated, but I think it will fit
in a day.
If lisp really had a strong job market, I would better think how I
would accomodate myself to lisp. There is no such a market in fact. No
jobs. So I'm using lisp privately as an MP tool and I have a freedom
to accomodate lisp to myself.
> Pardon? Regression testing catches everything???
If there are different things with coinciding names, any test where
the name is used would suffice.
Additionally, what you say is a subtle bug is a desired behavior for
me. As I want to have a freedom to
move _the_same_ symbol from package to package without serious
altering of my code.
Some libraries evolve in a spontateous way.
E.g. I have a library with portability utils, printer utilities and
code generation tools.
While this library is a small one, it fits nicely in one package and
in one source file. But time goes
and I see it is time to divide it into parts.
What would I do with "in-packages"? I'll just divide it into parts
(each part in one package).
Old package is retained and it contains the symbols which I didn't
want to separate.
Then I just recompile my code. When I see compiler complaining about
undefined function/variable, I go
to in-packages statement and add only that new package which is really
needed. This is a very simple action
which does not require me to deal with individual symbols. It is
likely that every application uses not the whole
divided library, but only some packages of it.
Please suggest what would you do in the situation.
Moreover, with "in-packages" I have smaller variety of contexts and
the contexts are generally simpler.
E.g. you have
(eval-blah-blah-blah `(defpackage :use-mostly-foo (:import-
from :foo ,@many-symbols) (:import-from :bar :one-symbol))
(eval-blah-blah-blah `(defpackage :use-mostly-bar (:import-
from :bar ,@many-symbols) (:import-from :foo :one-symbol))
You will likely have a mistake using one-symbol as it is ambigious not
in a code, but in your mind.
That bug might occur while you're switching between packages. Maybe my
mind is different, but I often
trying to use old keybindings when I switching from Word to Emacs and
it is annoying. The same goes to
other "contexts" and other entities that are kept in human memory.
Instead of that, I will use
(defpackage :use-mostly-foo (:use))
(defpackage :use-mostly-bar (:use))
(in-packages :use-mostly-foo :cl :foo)
(in-packages :use-mostly-bar :cl :bar)
Thus, I'll bound myself with a limitation not to use all the
flexibility of defpackage.
I will always qualify :one-symbol and it will never be ambigious. It
is enough to glance at tiny
in-packges statement to learn a context.
What goes to general purpose utilities, we see that
loop uses keywords, html generators use keywords, iterate (now is
beginning to) use keywords.
In an exceptional case where it is especially inconvinient, I can
(after careful consideration) use per
symbol approach, but I would avoid that.
It seem to be done, at least, in part.
http://paste.lisp.org/display/70334
I quote:
The overall idea is that we can "see" packages without using them.
The following rules apply:
i) symbol entered without a prefix is looked in *package* and any
packages that we "see". If it is found in exactly one package or all
found symbols in different packages are eq, then this symbol is used.
If more than one such a symbol exist, error is signalled. If no such
symbol exists, it is interned to *package*
ii) symbol entered with a prefix is found in the package designated.
If it does not exists then error signalled. If it is referred as
external, but it is internal indeed then error is signaled. Otherwise,
symbol is used.
It is just a "proof of concept". Code intended to be completely
portable. It is easy to implement a portable hierarchical packages
based on the code.
Flaws are:
- vectors are read incorrectly (structures are, possibly, too)
- code alters current readtable, so readtable API needs to be
redefined
- printer is not altered while it should be. Otherwise all symbols
from "seen" packages are printed with
package prefixes and it is not convinient.
- slime completion aint' work (some bugs are certainly there).
- possibly there are sequences of two (unread-char) and it might crash
all the idea. Don't know how to
check this as not all functions in the reader can be traced.
And here is a sample output:
(defpackage :tst (:use :cl))
(defpackage :p1 (:export :sym :s1))
(defpackage :p2 (:export :sym :s2))
(in-package :tst)
(SEE-PACKAGES)
Now seeing packages NIL
Now should err as there is no symbol p1::s2
(MULTIPLE-VALUE-LIST (IGNORE-ERRORS (READ-FROM-STRING "p1::s2"))) =>
(NIL #<SIMPLE-ERROR 206B83DC>)
(SEE-PACKAGES :P1 :P2)
Now seeing packages (:P1 :P2)
(READ-FROM-STRING "((s1 . s2) (p1::s1 p2:s2))") => ((P1:S1 . P2:S2)
(P1:S1 P2:S2))
Now should err as sym is ambigious
(MULTIPLE-VALUE-LIST (IGNORE-ERRORS (READ-FROM-STRING "sym"))) => (NIL
#<SIMPLE-ERROR 206BA1A4>)
(READ-FROM-STRING "(p1:sym p2:sym)") => (P1:SYM P2:SYM)
This is checked in SBCL and Lispworks and works identically (no wonder
as it is standard CL).
All this seemed to be a failure.
Backquotes killed me. And, SBCL reader seem not to be conforming - it
does not honor macro characters for .
So trying to use Pascal's code:
http://darcs.informatimago.com/darcs/public/lisp/common-lisp/reader.lisp
Hmm, did everyone add me to a kill file? Don't case. I have
implemented see-packages on top of Pascal Bourguignon portable common
lisp reader. Now I can make cl:compile-file and lisp REPL to use my
reader instead of a standard reader.
But Pascal Bourguignon's reader has a sticky GPL license and it likely
to contain some more bugs. No sence to publish what I have done under
GPL. Hope I'll get time to change ccl lisp reader (which is under
LGPL) to be a portable one. I consider SBCL reader as non-conformant
so I won't use it. CCL reader seem to be better.
Advantages or having a portable lisp reader would be:
- see-packges (was use-packages) and local with-packages - almost
implemented, but more work/research on printing is required
- portable hierarchical packages
- portable package locks
- readtime values for symbols (including read-time function bindings)
Meanwhile, I found that no change in package system would help to make
things cleaner. I still think see-packages is a great thing, due
mostly to the reason it allows to have package hierarchy isomorphic to
class hierarchy so that
use-package<->inherit from class.
I don't know how to use CLOS. In all other OO languages I have
learned, method names are not global. So we can have "add" method for
different classes having different signatures (which seem to be very
natural). CLOS requires a congruent lambda lists and it is a serious
limitation. If we took package=class approach in conjunction with #.
(with-package) read-time macro, this limitation could be overcomed -
we simply would have _different_ add symbols with different signatures
(please do not comment on that if you think that I am dumb/blub/non-
experienced programmer, save your time). I think that limitation of
having congruent lambda list is artificial, one might, say, use first
parameter class to determine a lambda list.
Finally I came to a conclusion that I would better have a clash
resolution/package management _tool_ instead. No extension of a
language solves problems by itself. See-packages still seem not to
allow have packages "like" cl package, which problem is addressed by
Tim Bradshaw' "conduit packages".
Interaction of see-packges with shadowing-import and shadow is not
defined yet.
Anyway, in a course of _any_ symbols reorganizations we have get
problems of several kinds:
- symbol clashes
- symbol moves from package to package and might get invisible
- trash symbols which occur due to :shadow
Using see-packages instead of use-package do not help that.
So, we might have a helper _tool_, maybe a running "daemon" which
periodically looks for a symbol problems. It might have the following
features:
- find and report supposed trash symbols
- edit defpackage form in an advance with a following loop:
1. take a defpackage (or, better, a defsystem) form
2. imagine what problems would occur while trying to run it
3. suggest hints/prompts to a user
4. get user decision
5. update defpackage/defsystem accoring to this decision
- support for creating package extensions
- Library update guide which takes libraries and compares them to new
versions to find a problems in advance.
In fact, every coder runs that "tool" from time to time, but the user
itself acts as a tool and its interpreter.
The situation might be improved and it to do it seem to be much easier
than reimplementing and testing a new lisp reader.
From: Tobias C. Rittweiler
Subject: Re: SymClashesHowToGetRid-Part-2 (Pascal, I seemed to fix a bug in your reader, take a look)
Date:
Message-ID: <87fxlqo8i9.fsf@freebits.de>
budden <········@gmail.com> writes:
> [...] I consider SBCL reader as non-conformant so I won't use it. CCL
> reader seem to be better. [...]
I don't think this was really supposed to be FUD, but let me stress that
the above statement is the personal opinion of the OP. There are other
people who do not share that sentiment at all.
-T.
> > I don't think this was really supposed to be FUD, but let me stress that the above statement is the personal opinion of the OP. [...]
That is Ok. I specifically said "I consider" to underline that it is
my personal opinion. If I was 100% sure, I would say "is non-
conformant". Maybe it didn't worth mentioning at all, but I spent some
time making SBCL reader portable (replacing SBCL-specific calls with
CL calls). I didn't finish this work though. Tobias, I guess you're
one of the SBCL developers, and I'd like to say: SBCL is a great work!
From: Tobias C. Rittweiler
Subject: Re: SymClashesHowToGetRid-Part-2 (Pascal, I seemed to fix a bug in your reader, take a look)
Date:
Message-ID: <873ahqnop5.fsf@freebits.de>
budden <········@gmail.com> writes:
> Tobias, I guess you're one of the SBCL developers, and I'd like to
> say: SBCL is a great work!
I'm not, actually. I did some reader-related sbcl hacking lately,
though. And this time I do indeed share your sentiment. :-)
-T.
On 17 nov, 20:08, budden <········@gmail.com> wrote:
> > > I don't think this was really supposed to be FUD, but let me stress that the above statement is the personal opinion of the OP. [...]
>
> That is Ok. I specifically said "I consider" to underline that it is
> my personal opinion. If I was 100% sure, I would say "is non-
> conformant". Maybe it didn't worth mentioning at all, but I spent some
> time making SBCL reader portable (replacing SBCL-specific calls with
> CL calls). I didn't finish this work though. Tobias, I guess you're
> one of the SBCL developers, and I'd like to say: SBCL is a great work!
This is not an issue of opinion, it's a question of fact. As far as I
know, the SBCL reader is compliant with the spec. If you are aware of
any specific problems, be explicit; otherwise, quit spreading FUD.
From: Tobias C. Rittweiler
Subject: Re: SymClashesHowToGetRid-Part-2 (Pascal, I seemed to fix a bug in your reader, take a look)
Date:
Message-ID: <87y6zgg37l.fsf@freebits.de>
"Thomas F. Burdick" writes:
> On 17 nov, 20:08, budden <········@gmail.com> wrote:
> >
> > > TCR wrote
> > >
> > > > I don't think this was really supposed to be FUD, but let me
> > > > stress that the above statement is the personal opinion of the
> > > > OP. [...]
> >
> > That is Ok. I specifically said "I consider" to underline that it is
> > my personal opinion. If I was 100% sure, I would say "is non-
> > conformant". [...]
>
> This is not an issue of opinion, it's a question of fact. As far as I
> know, the SBCL reader is compliant with the spec. If you are aware of
> any specific problems, be explicit; otherwise, quit spreading FUD.
Interpreting a standard can involve some leeway, even though I don't
think there is in this specific case. The OP delivered the background of
his opinion in the posting with message id
<····································@w24g2000prd.googlegroups.com>
I did not see any easy way to convince the OP otherwise. I hence did not
pursue the discussion.
-T.
Ok, I think now all is clear about reader conformance. Sorry for
starting to discuss it here. Let's return back to the topic. Are there
any ideas about package management tool?
On Mon, 2008-11-17 at 03:58 -0800, budden wrote:
> I don't know how to use CLOS. In all other OO languages I have
> learned, method names are not global. So we can have "add" method for
> different classes having different signatures (which seem to be very
> natural). CLOS requires a congruent lambda lists and it is a serious
> limitation. If we took package=class approach in conjunction with #.
> (with-package) read-time macro, this limitation could be overcomed -
> we simply would have _different_ add symbols with different signatures
> (please do not comment on that if you think that I am dumb/blub/non-
> experienced programmer, save your time). I think that limitation of
> having congruent lambda list is artificial, one might, say, use first
> parameter class to determine a lambda list.
yeah, this is a problem when things start to grow in size, but i think a
good idea is to start separating things into packages anyway then
..shadow the `add' from the "outer" package, then prefix it when one
need it..
while maybe not 100% optimal (i don't know what is), i think it is "ok"
and not a big problem
> > I don't know how to use CLOS. In all other OO languages I have
> > learned, method names are not global.
In fact, I was wrong. The second Right language I know, after lisp, is
T-SQL.
It is dynamic, has inherent persistant storage, convinient syntax,
strong reflexion capabilities,
keyword args, eval. But it does not have fully-featured namespaces and
it is not a great problem in a practice.
Maybe I'm simply too demanding... I'd like to have an ideal language
combining all advantages of lisp, sql and C++
without having their disadvantages. Is it reasonable?
Now I'd like to discuss package fix tool which I suggest. Has anyone
some ideas?
From: Kaz Kylheku
Subject: Re: Symbol clashes: how to avoid them. Part 2
Date:
Message-ID: <20081110141312.711@gmail.com>
On 2008-11-09, budden <········@mtu-net.ru> wrote:
> Hi Kaz, group!
> Not the probability, but the rate (probability per added symbol) can
> be calculated from the following initial data:
> 1. Structure of allowed signatures, including symbol name variance in
> parameters (say, keyword). This gives us a number of
> all distinct entities in a namespace. This number will be very large
> (billions, at least).
Yes, the space of possible symbols is very large.
However, the actual subspace that is used is not that large. Programmers do not
invent names by generating random strings that are lexically valid identifiers.
Look at English writing. There are twenty-six letters, but the probability of
encountering an 'e' in English text is greater than 1/26.
Holy crap, did you say you have a mathematics background?
> 2. Number of packages and a number of symbols currently in every
> package
And yet you yourself found that iterate clashed with another package. names.
Imagine: there are billions of possible symbols, enough to give every atom in
the universe its own unique symbol, and yet two packages both defined
COLLECTING.
How is that?
> 3. Rate of deletion relative to addition.
So this is your number between 0 and 1?
> But it has ho sence. First, we're talking about tradeoff, so we
> need to estimate relative risks. Absolute numbers would be useless.
The risk of reaching the wrong symbol via multiple use-package references is
high enough, and the payoff from the convenience is low enough, that it's a bad
engineering decision to do so.
> What would you put on the other side? My point that it is a reduction
> of readibility (in an extereme, all symbols are prefixed: maximum
> safety, minimum readability).
Nobody so far has argued for the use of fully qualified names everywhere.
We all agree that we like to use short names.
We all know that an unqualified name, in a given context, must uniquely resolve
to exactly one symbol.
> It is harder to read (and easier to
> overlook a semantic error) in a code which is not compact. User can
> forget, misprint or mix up a prefixes, which will lead just to the
> same result.
But then that mistake is plain in the code. A mistake caused by some symbol
silently jumping from one package to another is worse, because you can stare at
the incorrect reference and not realize that there is anything wrong.
> All this can hardly be estimated by a probability (maybe
> by a statistics).
Probability is just a summarizing result that comes from gathering statistics.
If you don't have the statistics, then you can't say something is improbable.
> But I had problems with importing in CL very often.
The current understanding (correct it if it's wrong) is that you had problems
with indiscriminate package use (called symbol "inheriting" by ANSI CL), not
with importing individual symbols. These so-called problems weren't bugs, but
inconveniences that you suffered.
You can't compare your personal inconveniences to subtle bugs caused by
careless convenience.
But note that the Common Lisp USE-PACKAGE will also not detect the problem that
I'm describing, so you are back to talking about apples, while I'm on oranges.
Even if USE-PACKAGE is changed to have lazy symbol clash detection, you still
have this problem; in this situation there isn't any clash.
It's prevented only by not using USE-PACKAGE.
On Fri, 2008-10-31 at 11:37 -0700, budden wrote:
> - every independent expert would say very definitely that a.b.c is
> much easier to read that (c-of (b-of a)).
I use (c-of (b-of a)), but it's more common to use or say (c (b a)).
Adding:
(defmethod c-of ((a a))
(c-of (b-of a)))
..or something, in cases where one very often need to reach `a' via `b'
is possible btw.
I don't think a.b.c is easier to read at all ... and it's not easier to
deal with either, which is what matters most in the long run anyway.
> Don't even say about (slot-value (slot-value a 'b) 'c).
I don't see how this relates, and I'm sure you know, but:
(let ((slot-name 'x))
(slot-value object slot-name))
> I was unable to explain why eight closing parens go in a row...
Hum .. a set of parens denote the start and end of a list -- add nesting
to this.
They don't "go" anywhere in _particular_ "by themselves" which is kind
of the point.
> Additionally I was disappointed when you told me about parenscript. MP
> with code generation from a lisp is an area of my strategic interests
> and if the author of parenscript is disappointed with it, it is a
> shock for me.
Uh, it was something I heard on IRC; it might not be true or accurate.
> Of course, one reason can be easily seen from the same
> a.b.c problem: javascript is just much shorter and easier to read.
I don't think so .. fiddling with syntax in JavaScript has been quite
annoying and time-consuming, and not only because of
browser-differences.
..might just be me; I prefer Lisp and Lisp-syntax. Doesn't this conflict
with what you said above btw.?
> Finally, I began to think that lisp is NOT a language for a web
> development. It might work well as an MP tool or as a server platform,
> but some more convinient syntax should be exposed to application
> developer.
> It would be ideally if it could combine adequate syntax
> with elegance of AST management and other successful design choices
> unique to lisp. Something like Nemerle or even shell. I think such a
> language is not too hard to develop using lisp as a platform, and I
> have already started some prototype.
I think you have conflicting ideas.
> What goes to symbolicweb, I think you might want to add some
> "symbolicweb-dsl" package, which would reexports most popular symbols
> from :sw, :tbnl, :cl-who, etc... And tell a users to use that
> symbolicweb-dsl. In fact, when you are combining new system from
> several smaller ones, you definitely need to specify how it is
> composed for potential users.
Yeah, this might work. I think it should be optional though; say SW uses
cl-who internally, but the user wants to use something else than cl-who
to generate HTML.