Thanks for responding Alex.

As you know, I'm just trying out picolisp in my spare time (hence my slow
responses on this list, sorry about that). To put some context to these
questions, I thought that using seperate namespaces to simulate a key/value
dictionary/hash-table would be a nice idea to play with, to understand picolisp
better.

(alists are nice and easy, but if you update it frequently cons'ing changes to
the begining, it gets slower & slower to work with the less frequently changing
key/values at the end of the alist)

Anyway, as the symbol-table/namespace itself is just a big hash-table, then all
we would need are: + a way to create a new namespace + check if a variable
exists in that namespace + get or set a variable in that namespace

I'm going to pull my original comments, and your replies, out of order and put
them under the above 3 headings, just to get a bit of order in here :)

(BTW, I hope this doesn't come across as "dogshedding" - or "arguing for
aguments sake". I'm genuinely interested to see where I can use picolisp in my
current stack - its 1/10th the memory footprint of racket!)

# a way to create a new namespace
#################################
>> (mk Dc)
>
> creates a new namespace 'Dc', and immidiately sets the current namespace
> back to 'pico'. That's all right.

It works, but it doesn't feel right. There's additional, unecessary work being
done here (switching the *current* namespace to the new one, then switching it
back to the old namespace).

I think that the lisp forms provided to cover the namespace functionality you
added to the vm ('symbols', and the ~ read macro) don't go far enough. They
cover one use case for namespaces, but not all potential uses.

Creating a new namespace, without changing the current namespace, would be one
addition ?


# check if a variable exists in that namespace
##############################################
Thats why I was asking about (interned?).

>> 3) is there a way to check if a symbol is interned, without actually
>> interning it and setting it to NIL (if it didn't previously exist).
>> Basically, some way to do (interned? 'sym) => T/NIL .
>
> Yes, but I can't think of a peculiarly efficient way at the moment. You
> could check with
>
>   (member "foo" (all))
>
> i.e. use a transient symbol to avoid the interning.
>
> Technically, an efficient way would be possible (avoiding 'all', which
> first collects all symbols into a list), by indexing directly into the
> name tree.

Is the symbol 'pico itself just an idx tree, or some derivative of that? I
didn't fully grok the explanation of idx tree's from the ref - is there a
Rosetta example (or other snippet) which you can point me to to explain them?
Thanks :)

> There is even such a function in the interpreter, i.e.
> 'isInternEXY_F' in src64/sym.l:37, but unfortunately there is no
> top-level frontend for it.
>
> Where would such a function be useful?

Being able to check for a variable, without the side-effect of automatically
interning it with NIL, would make NIL a more useful value to use.

Again, similar to 'creating a new namespace', you have more fine-grained
functionality in the vm, which hasn't been wrapped in picolisp forms.


# get or set a variable in that namespace
#########################################

> For one thing, you can easily set a variable in another namespace with:
>
>   (setq Dc~k1 123)

Yup - if we knew that the namespace is |Dc| and the variable in that namespace
is |k1|. But thats not what I'm trying to do in dset.

In the original example, inside (dset) we have Dict-ns = Dc, and Key = k1. So,
how would one access (set or get) the variable Dc~k1 , using just Dict-ns and
Key.

Is there some other way of accessing the contents of other namespaces, other
than using the ~ read macro?

>> However:
>> + even though (dset) switches the active symbol table with (symbols Dict-ns)
>> + and (symbols) returns <Dict-ns> as the active symbol table
>> + but the variable |Key| is still only set in the pico symbol table
>
> You must keep in mind that namespaces affect only the reader, not
> expressions which already have been read. The namespace which is active
> at the moment an expression is read determines which symbol with a given
> name will be in the expression.
>
> The expression
>
>> (dset Dc k1 (pack (time) " elapsed seconds"))
>
> is _read_ while 'pico' is the active namespace. A symbol 'k1' didn't
> exist at the moment the above 'mk' was called, so an entry for that name
> will be created in 'pico',

Interesting. So the reader automatically intern's any "free symbol" (for want of
a better term) that it finds, before evaluating the expr?

Is this just a way of avoiding "variable doesn't exist" exceptions in any
situation?

But ...

If a function doesn't evaluate the argument, any non-existant variable name
menioned in the call to that function are still interned, before the function
gets its (unevaluated) arg list.

Doesn't that seem, well, wrong?

####
(de dummy X (println "doing nothing!"))

(de k-vars ()
  (filter '((Sym)
            (= "k" (car (chop Sym))) )
    (all)))

pico λ: (k-vars)
-> (key kill keep keep> keep!> keep1> keep?> k-vars)
pico λ: (dummy k2)
"doing nothing!"
-> "doing nothing!"
pico λ: (k-vars )
-> (k2 key kill keep keep> keep!> keep1> keep?> k-vars)
####

Honestly, seems strange to me.

> and the expression '(setq Dc ...)' is
> returned, and then evaluated. It is irrelevant what 'dset' does with its
> arguments during that evaluation, the symbol 'k1' exists in 'pico'.

I still don't understand why the original example was failing though. I
understand that pico~k1 is interned (as NIL) before (dset) runs. But, once
inside dset, we've switched namespaces, and then:

        (eval (list 'setq Key Value))

where Key = k1, and Value = <whatever I passed in>. So why isn't
New-namespace~k1 now created?

>> 4) is there a way to concatenate two symbol-names together, without
>> creating a transient symbol? (symbol+ 'foo 'bar) => 'foobar
>
> No, but creating a transient symbol first does no harm. A transient
> symbol is just a symbol which happens not to be referred to from the
> current namespace. Each internal symbol is first created (by the reader)
> as a transient symbol, and then immediately interned.
>
> So (pack "foo" "bar") and (pack 'foo 'bar) both return "foobar", and
> (intern (pack "foo" "bar")) is just fine.

Ok. But there doesn't seem to be a way (that I can find) to dynamically combine
a namespace name, a '~', and a variable name

--
Regards,
       Imran Rafique
--
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe

Reply via email to