Re: Namespace support

2011-10-18 Thread Tomas Hlavaty
Hi Alex,

 Also, as we discussed on IRC, it would be nice to have the namespace
 name displayed in the repl prompt, e.g. via customizable prompt
 function as you suggested.

 I would suggest a new global variable '*Prompt', which may hold an
 'exe', so that

(setq *Prompt '(symbols))

 will result in a prompts

pico:

 The ':' is supplied automatically, and - as before - changes to '!' in
 breakpoints, '?' in error handlers '+' in stopped subprocesses and ''
 in sub-REPLs.

great!  Thank you.

Tomas
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: Namespace support

2011-10-14 Thread Tomas Hlavaty
Hi Alex,

 Also, as we discussed on IRC, it would be nice to have the namespace
 name displayed in the repl prompt, e.g. via customizable prompt
 function as you suggested.

 I would suggest a new global variable '*Prompt', which may hold an
 'exe', so that

(setq *Prompt '(symbols))

 will result in a prompts

pico:

 The ':' is supplied automatically, and - as before - changes to '!' in
 breakpoints, '?' in error handlers '+' in stopped subprocesses and ''
 in sub-REPLs.

great!  Thank you.

Tomas
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: Namespace support

2011-10-11 Thread Tomas Hlavaty
Hi Alex,

(setq x st1)
(setq x~sym1 5)
(print sym1 x~sym1 st1~sym1) # = NIL 5 5

great, it does what I was after!

 How can I create a new empty symbol table?

 This is easy. Just initialize it with an empty cons pair:

(setq st1 (cons))

 However, I just didn't want to support this on the API level (in the
 'syntax' function), because this is a very dangerous operation. If you
 should happen to set such an empty namespace to current, you are
 lost, as no symbol at all will be accessible any longer. You have no
 other choice than to enter Ctrl-D ;-)

Good point.

 How do I refer to a symbol table without making it the default one?

 Just the normal way, as a symbol. You can manipulate namespaces
 manually any way you like, as they are simply pairs of 'idx' trees.

OK.  I think the difference from traditional approach in other languages
is that the namespace must be visible in the current namespace.

 I don't see any problem. Here how this could be done (note that I use
 the convention to save and restore the current namespace in each
 module.  This allows to load each module in arbitrary contexts):

Yes, I was pointing out a problem to avoid which is not an issue with
your implementation:-D

Also, as we discussed on IRC, it would be nice to have the namespace
name displayed in the repl prompt, e.g. via customizable prompt
function as you suggested.

Cheers,

Tomas
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: Namespace support

2011-10-11 Thread Alexander Burger
Hi Tomas,

 Also, as we discussed on IRC, it would be nice to have the namespace
 name displayed in the repl prompt, e.g. via customizable prompt
 function as you suggested.

Oops, right. Forgot about that.


I would suggest a new global variable '*Prompt', which may hold an
'exe', so that

   (setq *Prompt '(symbols))

will result in a prompts

   pico:

The ':' is supplied automatically, and - as before - changes to '!' in
breakpoints, '?' in error handlers '+' in stopped subprocesses and ''
in sub-REPLs.


BTW, yesterday I added one more namespace-related function: 'local'. It
is intended to be used in modules, to make symbols explicitly local to
the current namespace.

For example, take a case like Henrik had before, where he wanted to
define a special version of 'match'. This symbol already exists in the
'pico' namespace, and should not be redefined. Then, we could write:

   (symbols 'strLib 'pico)

   (local match)

   (de match (Pat Data)
  ... )

You can then call it as

   (strLib~match Pattern Data)

The old 'match' function is available as before, as 'match', or
'pico~match'.


'local' is just a frontend to 'zap'. So

   (local bar foo mumble)

is the same as

   (mapc zap '(bar foo mumble))

but it is more readable, and makes the intentions more clear.

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: Namespace support

2011-10-11 Thread Alexander Burger
On Tue, Oct 11, 2011 at 12:08:10PM +0200, Alexander Burger wrote:
 I would suggest a new global variable '*Prompt', which may hold an
 'exe', so that
 
(setq *Prompt '(symbols))
 
 will result in a prompts
 
pico:
 
 The ':' is supplied automatically, and - as before - changes to '!' in
 breakpoints, '?' in error handlers '+' in stopped subprocesses and ''
 in sub-REPLs.

Now I did that, but with one difference: The namespace symbol is printed
only if it is not 'pico'. So it stays compatible in the default
namespace, and on versions other than 64-bits.

lib/debug.l now contains:

   (when (== 64 64)
  (setq *Prompt
 '(unless (== (symbols) 'pico) (symbols)) ) )


The '*Prompt' global variable, however, is available also in 32-bits and
ErsatzLisp.

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: Namespace support

2011-09-29 Thread Alexander Burger
Hi all,

please note that I released a slight modification of the namespace
support: The 'load' function will preserve the current namespace, even
if it is changed by 'symbols' while loading a file.


The reasons can be seen best in the example from the previous discussion
with Tomas:

 Programmer A develops a groundbreaking library called xml.
 Programmer B develops another groundbreaking library called xml.
 Programmer C develops a library which uses A's xml library.
 Programmer D develops a library which uses B's xml library.
 Programmer E develops an application using libraries developed by
 programmers C and D.
 ...
### File libA.l ###
(setq ns (symbols 'a 'pico))
 
(de xml (A) 'A)
 
(symbols ns)
 
 
### File libB.l ###
(setq ns (symbols 'b 'pico))
 
(de xml (B) 'B)
 
(symbols ns)
 
 
### File libC.l ###
(load libA.l)
(setq ns (symbols 'c 'a))
 
(de foo (X)
   (xml X) )
 
(symbols ns)
 
 
### File libD.l ###
(load libB.l)
(setq ns (symbols 'd 'b))
 
(de foo (X)
   (xml X) )
 
(symbols ns)
 
 
### Program E ###
(load libC.l libD.l)
 
(println (c~foo) (d~foo))
 
 Output:
A B

As you see, this ends up with saving the current namespace in each
module (source file), by keeping it in a transient symbol ns, defining
the module's contents, and then restoring it with (symbols ns).

I think this is necessary, because otherwise I got a surprising behavior.

If I simply did

   ### File libA.l ###
   (symbols 'a 'pico)
   (de xml (A) 'A)

   ### File libB.l ###
   (symbols 'b 'pico)
   (de xml (B) 'B)

   ### File libC.l ###
   (load libA.l)
   (symbols 'c 'a)
   (de foo (X) (xml X))

   ### File libD.l ###
   (load libB.l)
   (symbols 'd 'b)
   (de foo (X) (xml X))

then back in the the main program

   (load libC.l libD.l)
   (println (c~foo) (d~foo))

I got an error: c -- Bad symbol namespace

Why that? Answer: After loading libC.l, and then libD.l, the current
namespace is on 'd'.

The namespace 'c', however, was defined while namespace 'a' was current
(after loading libA.l in libC.l), so 'c' is neither in 'pico' nor in
'b' (which was then used to derive 'd').

'c' is accessible only via 'a'.

'foo' could now be accessed as a~c~foo, because 'a' was inherited from
'pico' - 'b' - 'd' ('b' was created later in 'pico' than 'a').

Confusing, isn't it?

It is desirable to have 'c' accessible from 'pico' (or whatever
namespace was current when the main program loaded the two libraries),
so that c~foo and d~foo are valid.

The only clean way I can see is to save the currently active namespace
at the beginning of a module. For that reason I wrote in the initial
exampes, at the beginning of each module

   (setq ns (symbols 'newLib 'oldLib))

and at the end

   (symbols ns)

This looks ugly. And as it is indeed needed for _each_ module, we may as
well hard-code it into the 'load' function.


With that, the situation suddenly becomes very simple and clear. A
source file (or several nested source files) gets its own namespace
simply by calling (symbols 'newLib 'oldLib) at the beginning, possibly
after loading other required sources.

Here, 'oldLib' can be anything, it must not necessarily be the current
namespace. It should be whatever this module needs, i.e. where it builds
upon. However, 'newLib' will be automatically created in the current
namespace, i.e. the namespace of the caller.

As 'symbols' sets the new current namespace to 'newLib', all newly
created symbols will go into that namespace.

(Caution! You should be aware that all this namespace stuff operates
strictly on the symbol level. It is not concerned about values,
definitions, properties etc. of the involved symbols. Note the term
created symbols in the previous paragraph. Especially, if a symbol
already exists in 'oldLib', it will stay there, of course, and possible
definitions for that symbol will be visible there too).


When 'load' finishes, the current namespace is automatically reset to
the previous one. Now the new symbols in 'newLib' can be either accessed
via the '~' read macro

   newLib~foo

or by switching completely to the new namespace with

   (symbols 'newLib)

and further referring to it simply as 'foo'.


Side note: The above tests print the warning

   # d redefined

This is correct, because 'd' is a debugger function. In practice, it
would be better to select non-conflicting names for the namespaces.
Besides this, the examples work (just the 'd' function is gone ;-)

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: Namespace support

2011-09-21 Thread Alexander Burger
On Mon, Sep 19, 2011 at 07:56:42PM +0200, Tomas Hlavaty wrote:
 2. importing a symbol from another namespace (with 'intern')
 
 Renaming a symbol is not interesting.  Importing maybe is, to a certain
 point.

Now I added an 'import' function, a simple frontend to 'intern'. With
that, we can conveniently import symbols from other packages:

   (import libA~foo libB~bar)

An Import conflict error is issued when a symbol with the same name
already exists in the current namespace.

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: Namespace support

2011-09-20 Thread Henrik Sarvell
It solves the long function name problem and due to class naming conventions
it improves the global namespace problem quite a bit.

The long function name solution solves the the global namespace problem
completely but is imo not a good solution as it can easily become absurd.


On Tue, Sep 20, 2011 at 1:33 PM, Tomas Hlavaty t...@logand.com wrote:

 Hi Henrik,

  (func '+Kadabra arg1 arg2)
 
  is shorter than:
 
  (foo.bar.blabla.abra.kadabra.func arg1 arg2)

  no, it's similar to (Kadabra.func arg1 arg2).
 
  (func '+Foo.bar.blabla.abra.kadabra arg1 arg2) is similar to
  (foo.bar.blabla.abra.kadabra.func arg1 arg2).

  My example implied that +Kadabra is a sublass of a sublcass and so on up
 to +Foo.

 ok.

 But it still doesn't solve the nature of the problem you are trying to
 address.  It only shifts it a bit.  Instead of having potential function
 name clashes, now you have potential class name clashes.  +Foo still
 must be unique in the whole picolisp process.  How is that better than
 func being unique in the whole picolisp process?

 Cheers,

 Tomas
 --
 UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe



Re: Namespace support

2011-09-19 Thread Alexander Burger
Hi Tomas,

 Personally I am not a fan of namespaces in picolisp.

Yes. As you know, I am neither.

However, the current implementation won't do any harm, as long as it is
not actually used (and I won't probably use it ;-)

It is a simple extension of the general principles underlying PicoLisp
symbols.

Until now, a symbol was either interned or not interned into the global
symbol table (if we ignore external symbols for the moment, and regard
transient symbols as a special way of implicit interning / uninterning a
symbol).

Now, with the 'symbols' extension, there may be several global symbol
tables, with one of them active at a given time. A new symbol table is a
copy of an existing one. Thus, a symbol may be either non-interned, or
interned in one or several symbol tables.

It is all about symbols, not about names. For that reason, I avoided the
term namespace for the new function, and called it symbols.


 However, once there is support for namespaces, as Christian points out,
 there are other operations that should be supported.  It seems to me
 that your suggested implementation solves the problem of symbol name
 clashes, but introduces a new problem of namespace name clashes.  Do I
 read that right?

Probably. Fact is, now we may have two or more _interned_ symbols with
the same name, as long as they are interned into different symbol
tables.

But I wouldn't call that solving symbol name clashes. There was never
a clash of symbol names, because only a single internal symbol with a
given name could ever exist in the system. Instead, the problem were
definition clashes (trying to give different values or properties to a
symbol). Henrik solved that for himself with OO techiques.

Concerning namespace name clashes: I can see two problems at the
moment:

   1. renaming a symbol (with 'name'), and
   2. importing a symbol from another namespace (with 'intern')

Renaming was (and is) allowed only for uninterned symbols. To rename an
interned symbol, you must first unintern it (with 'zap'), assign a new
name (with 'name') and then intern it again (with 'intern'). The problem
now is that the programmer is in charge of uninterning the symbol from
all symbol tables, which might not be feasible, and is also probably not
what was intended with the renaming in the first place.

Importing symbol from another namespace can be done with

   (intern 'myNames~Foo)
   - Foo

This will make the symbol 'Foo' from 'myNames' available as an internal
symbol in the current namespace.

However, the pitfall is that if 'Foo' already existed in the current
namespace, 'intern' will return _that_ symbol - and not the symbol with
the same name in 'myNames'. Thus, the import should actually be
something like

   (unless (== 'myNames~Foo (intern 'myNames~Foo))
  (msg 'Foo  is already interned) )


 One of the most important operations on namespaces
 should be creating a local name (alias) for it.  Common Lisp didn't get
 this right, for example, so it would be great if picolisp avoided that
 flaw.

I don't see a way. That's what I meant when in the past I said that
namespaces don't go well with the general principles of symbols.

In PicoLisp, the name is an attribute of the symbol, not of the
namespace. A symbol may have only one single name. It may be referred to
from one or several symbol tables. An alias would require that the name
is stored in the symbol table instead of the symbol, and then have the
symbol hold a list of all namespaces that refer to it. Printing would
look up the actual name in the current namespace.

This would be quite some overhead, destroying the once cell per symbol
feature, and make things even more complicated for the programmer.

Also I think that an alias would not have such very big advantages over
writing the full specification 'myNames~Foo'.

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: Namespace support

2011-09-19 Thread Henrik Sarvell
 Importing symbol from another namespace can be done with

   (intern 'myNames~Foo)
   - Foo

 This will make the symbol 'Foo' from 'myNames' available as an internal
 symbol in the current namespace.


This is imo a must have feature, it has to be up to the programmer to avoid
clashes as it is his problem to avoid similar pitfalls in all interpreted
languages.

Contrast with Clojure for instance, the below will not compile so the
compiler protects you from yourself:

(require foo.bar.blabla.abra.kadabra.func as func)

(defn func)

Having to write the full name all the time could easily become comical, as
in my above Clojure example. This is also one of the reasons I have leaned
towards OO encapsulation since I then can subclass everything.

(func '+Kadabra arg1 arg2)

is shorter than:

(foo.bar.blabla.abra.kadabra.func arg1 arg2)



On Mon, Sep 19, 2011 at 2:04 PM, Alexander Burger a...@software-lab.dewrote:

 Hi Thorsten,

  one question with regards to this topic:
  what would be the advantage of namespaces in Picolisp over
  namingconventions like in Emacs Lisp?

 Right. Not much.

  'gnus-function-name' for all functions in gnus library
  'dired-function-name' for all functions in dired library etc

 Yes. Such conventions make things transparent. The drawback might just
 be readability of the longish symbol names.

 I suggested something like this in my reply to Henrik (on Sep 5th, using
 the 'dot' as a delimiter):

  A call like
 
 (foo '+Pckg arg)
 
  is in no regard more encapsulating the namespace then
 
 (foo.Pckg arg)

 Cheers,
 - Alex
 --
 UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe



Re: Namespace support

2011-09-19 Thread Jakob Eriksson
On Mon, Sep 19, 2011 at 02:51:32PM +0700, Henrik Sarvell wrote:
 Having to write the full name all the time could easily become comical, as in
 my above Clojure example. This is also one of the reasons I have leaned 
 towards

+1

Imagine all the rants which could be made about code full of both parens AND 
ultralong
function names. :-)

//Jakob
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: Namespace support

2011-09-19 Thread Thorsten
Jakob Eriksson ja...@vmlinux.org writes:

 On Mon, Sep 19, 2011 at 02:51:32PM +0700, Henrik Sarvell wrote:
 Having to write the full name all the time could easily become
 comical, as in my above Clojure example. This is also one of the
 reasons I have leaned towards

 +1

 Imagine all the rants which could be made about code full of both
 parens AND ultralong function names. :-)

Hi Jakob,
from my 'innocent' newbie perspective to both, PicoLisp and Emacs Lisp,
I can report that ultralong function names and straight documentation
conventions in Emacs Lisp helped me _a lot_ in understanding elisp source code,
even without full understanding of the language, while lack of
documentation (except for the core functions) and cryptically short
functions names do represent an obstacle when trying to understand
Picolisp source code. 

Imho, this is one topic were Picolisp could improve by copying some
habits from the Emacs Lisp community. 
And, with an editor like Emacs, those ultralong function names are not as
impracticable as one would think. 
Cheers
Thorsten

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: Namespace support

2011-09-19 Thread Thorsten
Henrik Sarvell hsarv...@gmail.com
writes:

 I can understand both your arguments Thorsten but in the end there
 must've been a reason why you found PicoLisp interesting enough that
 you wanted to try it out as opposed to using elisp/common lisp for
 everything.

 Perhaps it was the brevity and clarity of syntax, the minimalism?

There are more than enough reasons to find PicoLisp interesting, and you
mentioned a few. I'm only saying that the documentation string for each
function in elisp is kind of helpfull, and so are the 'speaking''
function names, although they do seem comically long sometimes. 

 I can tell you this, I didn't go for PicoLisp because it enabled me to
 write packages with the help of function names of the form
 foo.bar.func.

I think in this case it would even be possible to 'eat your cake and
have it', at least when using PicoLisp mode in Emacs. There might be a way to
stick to PicoLisp minimalism, but have some documentation conventions
with very little extra effort. Having more time now, I'll give it a try,
but I'm not sure if my elisp is good enough to succeed. 

Cheers
Thorsten


 On Mon, Sep 19, 2011 at 4:29 PM, Thorsten
 quintf...@googlemail.com
 wrote:

 Jakob Eriksson ja...@vmlinux.org writes:

  On Mon, Sep 19, 2011 at 02:51:32PM +0700, Henrik Sarvell wrote:
  Having to write the full name all the time could easily become
  comical, as in my above Clojure example. This is also one of the
  reasons I have leaned towards
 
  +1
 
  Imagine all the rants which could be made about code full of both
  parens AND ultralong function names. :-)

 Hi Jakob, from my 'innocent' newbie perspective to both, PicoLisp
 and Emacs Lisp, I can report that ultralong function names and
 straight documentation conventions in Emacs Lisp helped me _a lot_
 in understanding elisp source code, even without full
 understanding of the language, while lack of documentation (except
 for the core functions) and cryptically short functions names do
 represent an obstacle when trying to understand Picolisp source
 code.

 Imho, this is one topic were Picolisp could improve by copying
 some habits from the Emacs Lisp community.  And, with an editor
 like Emacs, those ultralong function names are not as
 impracticable as one would think.  Cheers Thorsten

 --
 UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: Namespace support

2011-09-19 Thread Tomas Hlavaty
 (func '+Kadabra arg1 arg2)

 is shorter than:

 (foo.bar.blabla.abra.kadabra.func arg1 arg2)

no, it's similar to (Kadabra.func arg1 arg2).

(func '+Foo.bar.blabla.abra.kadabra arg1 arg2) is similar to 
(foo.bar.blabla.abra.kadabra.func arg1 arg2).

Cheers,

Tomas
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: Namespace support

2011-09-18 Thread Tomas Hlavaty
Hi Alex,

 for namespaces convenient. Scheme implementations provide an import
 statement that let's you include symbols from one namespace into your
 current one. This is not yet exciting but you can manipulate the
 symbols during this import:
 
 - prefixing them
 - renaming them
 - filtering out (or in) certain symbols but not all.
 
 I conclude that such procedures are added easily now that symbols
 exists.

 Right. This could be done on the Lisp level, but we must be careful.

 For example, renaming a _symbol_ is possible only for transient
 symbols, so such a function would need to remove the symbol from all
 namespaces, rename it, and intern it again.

Personally I am not a fan of namespaces in picolisp.

However, once there is support for namespaces, as Christian points out,
there are other operations that should be supported.  It seems to me
that your suggested implementation solves the problem of symbol name
clashes, but introduces a new problem of namespace name clashes.  Do I
read that right?  One of the most important operations on namespaces
should be creating a local name (alias) for it.  Common Lisp didn't get
this right, for example, so it would be great if picolisp avoided that
flaw.

Cheers,

Tomas
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: Namespace support

2011-09-16 Thread Alexander Burger
Hi Christian,

 for namespaces convenient. Scheme implementations provide an import
 statement that let's you include symbols from one namespace into
 your current one. This is not yet exciting but you can manipulate
 the symbols during this import:
 
 - prefixing them
 - renaming them
 - filtering out (or in) certain symbols but not all.
 
 I conclude that such procedures are added easily now that symbols
 exists.

Right. This could be done on the Lisp level, but we must be careful.

For example, renaming a _symbol_ is possible only for transient symbols,
so such a function would need to remove the symbol from all namespaces,
rename it, and intern it again.

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: Namespace support

2011-09-16 Thread Alexander Burger
Hi Henrik,

 As far as I can tell this makes the (context) thing you implemented before
 pretty redundant or is it worth keeping?

Yes, I would say we forget about that one.

It was a completely different concepts. It didn't implement symbol
namespaces (all symbols were still in the single global internal
lookup structure), but handled method dispatch to an implicit list of
classes (the context).

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe