(symbols) inside a function
Alex, Tomas, Axel (and all other picolisp coders out there), Another newbie question here, this time using (symbols) inside a function. The intention behind the code (see below) is pretty simple. (mk) will create a new namespace (well, a new symbol table), and (dset) should set a variable in a specified namespace. However: + even though (dset) switches the active symbol table with (symbols Dict-ns) + and (symbols) returns as the active symbol table + but the variable |Key| is still only set in the pico symbol table Some questions (in addition to the obvious "why isn't this working?"): 1) What am I doing wrong when I'm trying to (setq) the variable? 2) is there a way to create a new symbol-table/namespace without it becoming the active one? 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 . 4) is there a way to concatenate two symbol-names together, without creating a transient symbol? (symbol+ 'foo 'bar) => 'foobar As always, thanks in advance :) ### code (dicts2.l) (de mk X # switch back to orig ns, after creating new ns (symbols (symbols (car X) 'pico)) ) (de dset X (let ( Dict-ns (car X) # switch to Dict-ns Orig-ns (symbols Dict-ns) Key (cadr X) Value (eval (caddr X)) ) (prinl (pack "Current namespace is " (symbols))) (prinl (pack "Setting " Key " to " Value)) (eval (list 'setq Key Value)) (symbols Orig-ns) (prinl (pack "Current namespace is " (symbols))) )) (mk Dc) (dset Dc k1 (pack (time) " elapsed seconds")) (prinl (pack "pico~k1 => " pico~k1)) (prinl (pack "Dc~k1 => " Dc~k1)) ### output # note: this is with (de *Prompt (pack (symbols) " λ")) pico λ: (load "/home/imran/src/picolisp/labs/dicts2.l") Current namespace is Dc Setting k1 to 17820 elapsed seconds Current namespace is pico pico~k1 => 17820 elapsed seconds Dc~k1 => -- Regards, Imran Rafique (skype: imran_rafique) -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
Re: (symbols) inside a function
Hi Imran, > The intention behind the code (see below) is pretty simple. (mk) will > create a new namespace (well, a new symbol table), and (dset) should > set a variable in a specified namespace. For one thing, you can easily set a variable in another namespace with: (setq Dc~k1 123) This works, btw, also with further indirections: (setq Dc~ns1~ns2~k1 777) > However: > + even though (dset) switches the active symbol table with (symbols Dict-ns) > + and (symbols) returns 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. > 1) What am I doing wrong when I'm trying to (setq) the variable? > (mk Dc) creates a new namespace 'Dc', and immidiately sets the current namespace back to 'pico'. That's all right. 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', 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'. > 2) is there a way to create a new symbol-table/namespace without it > becoming the active one? Yes. The above 'mk' is fine for that. > 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. 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? > 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. Cheers, - Alex -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
Re: (symbols) inside a function
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 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 (print
Re: (symbols) inside a function
On Wed, 1 Feb 2012 05:53:11 -0800 Imran Rafique wrote: > 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) > Why not use a 'idx tree then? http://software-lab.de/doc/refI.html#idx ## # I used 'name here to prevent accidental clobbering (de iset (Tree Key Value) (set (or (car (idx Tree Key)) (prog1 (name Key) (idx Tree @ T)) ) Value ) ) (de iget (Tree Key) (val (car (idx Tree Key))) ) ## Tests ## : (iset 'mydict "Foo" 42) -> 42 : (iset 'mydict "Bar" T) -> T : (iset 'mydict "Bam" "Baz") -> "Baz" : (iget 'mydict "Foo") -> 42 : (iget 'mydict "Bam") -> "Baz" : (iget 'mydict "Bar") -> T : (mapcar show (idx 'mydict)) "Bam" "Baz" "Bar" T "Foo" 42 -> ("Bam" "Bar" "Foo") ### > 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 > [...] Cheers, José -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
Re: (symbols) inside a function
Hi Imran, > 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 That's perfect. No hurry :) I also want to spend more time concentrating on project work. > 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. While this is theoretically possible, I would stronly disadvise it. Namespaces are a huge overhead, if you just want to create some data lookup structure. Calling 'symbols' creates a copy of the current namespace, so this means that for a (relatively small) namespace of 1000 symbols, a tree of 1000 nodes (or roughly 1500 cells) is copied. That's 24000 bytes of memory. Searching for a few symbols in that big tree is also unnecessarily slow. > (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 A simple linear list search is for up to 100 or so items probably faster than a lookup in the above large tree. > key/values at the end of the alist) You might consider using symbol properties then. Properties are implemented using a last-recently-used scheme. When a property is found with 'get' or related functions, it is moved to the front of the list. But for large data sets, 'idx' (as José Romero pointed out) is probably better. In fact, namespaces internally have the same structure as 'idx' trees. > 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 Yes, but with a really big overhead (see above). > (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!) OK. > >> (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). Compared to the amount of work of creating the namespace (copying thousands of tree cells), the setting of the current namespace is ridiculously small. It involves not more than switching a pointer. The creation and immediately setting of the namespace is just convenient. The intention of namespaces is to build indpendent modules, and in such cases you will want to do (symbols 'newspace 'pico) (de a () ...) (de b () ...) If you put such a code sequence into a single file, you have an isolated module, because 'load' restores the current namespace when it is done, effectively making 'newspace' available in 'pico'. > 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. To my feeling, they fit together perfectly. At least for the intended purpose. > Is the symbol 'pico itself just an idx tree, or some derivative of that? I Yes. To be precise: It is a cons-pair of two idx trees, one for short names (7 or less characters), and one for long names. But: The internal matching algorithm is not compatible to 'idx'. It doesn't use comparison functions (=, < etc.) on the symbol names (strings) as 'idx' does, but compares complete chunks of 64-bit words. This is the reason for the distinction between short and long words. Therefore, 'idx' can't really be used with namespaces. > 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? Yes, for example http://rosettacode.org/wiki/Associative_arrays/Iteration http://rosettacode.org/wiki/Anagrams http://rosettacode.org/wiki/Anagrams/Deranged anagrams http://rosettacode.org/wiki/Hamming_numbers http://rosettacode.org/wiki/Huffman_coding http://rosettacode.org/wiki/Inverted_index http://rosettacode.org/wiki/LZW_compression http://rosettacode.org/wiki/Priority_queue http://rosettacode.org/wiki/Set http://rosettacode.org/wiki/Sokoban > Is there some other way of accessing the contents of other namespaces, other > than using the ~ read macro? Not really, AFAIK at the moment. > > 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? Yep. This is a ve
Re: (symbols) inside a function
Jose & Alex, Please excuse my rudeness in not replying sooner (on business, then Yosemite trip). Thanks for the pointers on idx trees. -- Regards, Imran Rafique 2012/2/1 José Romero : > Why not use a 'idx tree then? http://software-lab.de/doc/refI.html#idx > > ## > # I used 'name here to prevent accidental clobbering > (de iset (Tree Key Value) > (set > (or > (car (idx Tree Key)) > (prog1 (name Key) (idx Tree @ T)) ) > Value ) ) > > (de iget (Tree Key) > (val (car (idx Tree Key))) ) > > ## Tests ## > : (iset 'mydict "Foo" 42) > -> 42 > > : (iset 'mydict "Bar" T) > -> T > > : (iset 'mydict "Bam" "Baz") > -> "Baz" > > : (iget 'mydict "Foo") > -> 42 > > : (iget 'mydict "Bam") > -> "Baz" > > : (iget 'mydict "Bar") > -> T > > : (mapcar show (idx 'mydict)) > "Bam" "Baz" > "Bar" T > "Foo" 42 > -> ("Bam" "Bar" "Foo") > ### On 1 February 2012 19:59, Alexander Burger wrote: >> 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? > > Yes, for example > > http://rosettacode.org/wiki/Associative_arrays/Iteration > http://rosettacode.org/wiki/Anagrams > http://rosettacode.org/wiki/Anagrams/Deranged anagrams > http://rosettacode.org/wiki/Hamming_numbers > http://rosettacode.org/wiki/Huffman_coding > http://rosettacode.org/wiki/Inverted_index > http://rosettacode.org/wiki/LZW_compression > http://rosettacode.org/wiki/Priority_queue > http://rosettacode.org/wiki/Set > http://rosettacode.org/wiki/Sokoban -- UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe