a newbie question

Started by lithper, March 22, 2008, 03:09:18 PM

Previous topic - Next topic

lithper

Reference for functions like those from the "ref" family, "find", "match" etc. - operators for work with lists - supposedly can take (list) as search arguments inside a bigger list (L):
(ref (list) L)
It works OK as examples from the docs show if (list) is a known set of symbols:
(set 'L '(a b c d 1 2 3))
(ref 'd L)

However, if and when you calculate your search list , this invocation becomes impossible:
(list? (3 1 L))
         :- true

(ref (3 1 L) L)
        :- read error message from newLisp


The only variant I stumbled upon that works is converting the calculated list into a string, and then clumsily stripping its (" -- and "), if the term contains one element. Searching for a string that matches a symbol in a given list then works.



Where is the answer? It may be a very simple, newbie question.



I.e. the problem as far as i can guess is in the treatment of brackets and quotes by nL.

If our list includes (d 1) as a _sublist_ - (a b c (d 1) 2 3 , the match for '(d 1) will happen, and so examples from documentation work.

But i see no way to match for a subsequence in a flat list, if the sequence is produced by a previous calculation as a list and so is bracketed.



For example - I calculate something that produces "list_q" which is ("1" "0")

I want to find where in list L that "1" is included:

(ref  ( 0 1 list_q)  L)

     :- will fail

because NL wants to treat brackets and quotes as literal part of the symbol in searching the list L.

cormullion

#1
You can look for things in lists like this:


(set 'List '(a b c d 1 2 3))
(println  (ref (List 1))) ; location of a "1" in List
;-> 4 - because "1" is at index 4


This is using the new (9.3) syntax for finding things in lists - where (alist thing) looks for 'thing' in alist. This isn't the same as (alist n), which is an index operation, where n is an index number. I think the two are different because you can only use the first form at certain places in certain functions... I don't think you can pre-build the first form, but you should be able to pre-build the second:


(set 'List '(a b c (d 1) 2 3))
(set 'l '(d 1))
(println (ref l List)) ; look for '(d 1) in List
;-> (3)


I might be wrong, it's new to me too. :)

Lutz

#2
There are two issues here:



First is a confusion between the old flat syntax (ref <exp> <list>) and the new parenthesized syntax (ref (<list> <exp>)). Second issue is, that 'ref' can only look for elements of a list not subsequences. You example must be written in the parenthesized syntax:


(set 'L '(a b c d 1 2 3))
> (ref (L (3 1 L)))
()
>


but returns an empty list because is (3 1 L) which is (d) is not an Element of L. Only 'd' would be an element of L. But this would find (d):


(set 'L '(a b c d (1 (d) 2) 3))  
> (ref (L (3 1 L)))
(4 1)
>


(d) is the sublist made from the first d in L, which is found at offset (4 1)



Use the old flat syntax only when <exp> is not a parenthesized expression. Or use the flat syntax as in Cormullion's last example.



ps: the old flat syntax will be deprecated and later eliminated for 'ref' and 'ref-all', the new 'set-ref', 'ref-set' and 'set-ref-all' already use only the new syntax.

lithper

#3
Quote from: "Lutz"
...but returns an empty list because is (3 1 L) which is (d) is not an Element of L. Only 'd' would be an element of L. But this would find (d):


(set 'L '(a b c d (1 (d) 2) 3))  
> (ref (L (3 1 L)))
(4 1)
>

(d) is the sublist made from the first d in L, which is found at offset (4 1)


That is exactly what the problem is. Unless someone somehow turns lists in your program from (a b c d e f) into (a b c (d) (e) (f)), exactly for the elements you might be likely to search for in the future, the operators will fail.



So, examples.:
(set 'L '("a" "b" "c" "d" "1" "2" "3"))       ; list to search in
(set 'pl '("h" "d"))     ; list for queries - not known as symbols to the programmer, it is caclucalted by the program

(ref  (L    (1 1(string(1 1 pl)))   )   )  ---> (3)     ;this insanity works


If the double quotes are omitted in one of the lists, no search will work (as quotes are treated as part of the name, not some attribute of a string or sym data type, that the language converts between?)


(ref  (L    (1 1 pl)   )   )         ; will not work

Example two:


(set 'M '(a b c (d) 1 2 3))      ; list to search in
(set 'pl '(h d))    ; list to form search term from
 (ref (M    (1 1 pl))      )  -------> (3)   ; this works

But if (d) in M is not bracketed, i.e. not born as a sublist through some clarivoyance by the programmer, ref's and find's agains the flat list will fail.



SO:

(a) ("d" "e") is not the same as simple (d e ) - and list operators will fail on the difference

(b) no list operators, such as find and ref, work on flat lists - unless the exact literal symbol is known to the programmer. I.e. search items for find and ref could not be calculated??

(c) .. They can be calculated, but only in a couple of special cases -- if it's the list of strings, and the search item is converted into a string and stripped of brackets and quotes, which NL understands as part of their names? -- or if the search item is sublisted in the list in which we are searching  



This is what the problem is - or do I miss something very simple?

Lutz

#4
Not sure I understand, let me take it in little steps, sorry if the following looks trivial and is not what you where asking for:


(set 'L '(a b c d e (f) (g h (i j))))

(ref (L 'd)) => (3)    ; looking for the symbol d
(ref (L '(f))) => (5)     ; looking for a list with f in it (f)
(ref (L '(i j))) => (6 2) ; looking for a list (i j)
(ref (L 'j)) => (6 2 1)  ; looking for symbol j


I believe what you are trying to do is look for the sequence 'b c d', not the list (b c d) but the subsequence of the 3 elements b c d in the list L.  This is not possible with 'ref'. 'ref' can find only one element in the list not a sequence of various elements. An element of course could be a list by itself.



if you are looking for sequence you could try 'match' but it doesn't give you the position of the sequence.

lithper

(a) no search for subsequence - ok, I could live with that.



(b) .. I am trying to match something that I do not know to be able to use literally, something that my program will calculate -- against a flat list of the same type items.



I.e. I cannot  say (ref 'd L) - because I have no idea if it's likely to be 'd or 'e or 'f - that is something my prog will calculate.



Now, the example of that calculation:

my flat list is (set 'L '("a" "b" "c" "d"))

my calculated something produces ("h" "d") - and I have no idea about it because it's produced as, say, list named dl - now I'm trying to see, if that second element "d" is in L, and if so, do something to L.:

(ref (L (1 1 dl)) ) -- and it will never match.



It seems that:

---1- no finds or refs in a flat list are possible at all? Or

---2- might be possible in 2 special cases only: someone was clever to create L in a different way, no a flat list, but as ("a" "b" "c" ("d")) ??!

or, secondly, only in case of lists of strings, I might get my result if instead of straightforward

(ref (L (1 1 dl))

I would use

(ref (L    (1 1(string(1 1 dl)))     ) -- i.e. convert my search item into a string and trim/strip it first

cormullion

#6
Quotethe old flat syntax will be deprecated and later eliminated for 'ref' and 'ref-all', the new 'set-ref', 'ref-set' and 'set-ref-all' already use only the new syntax.


Please don't remove it! I don't want to fix broken scripts every time there's a new version of newLISP :)

Lutz

#7
QuoteI.e. I cannot say (ref 'd L) - because I have no idea if it's likely to be 'd or 'e or 'f - that is something my prog will calculate.



(set 'L '(a b c d e (f) (g h (i j))))

(set 'x 'd) ; x is the unknown thing you are looking for

(ref x L)   => (3)
(ref (L x)) => (3)

(set 'y  '(i j)) => (6 2)


Quote(set 'L '("a" "b" "c" "d"))  ..... (ref (L (1 1 dl)) ) -- and it will never match.


because the expression (L 1 1 dl) does not return "d" but the list ("d"). What you want is:


(set 'L '("a" "b" "c" "d"))
(set 'dl '("c" "d"))

(ref (L (dl 1))) => (3)

; or coming back to your old example

(set 'L '(a b c d e f g))

(ref (L (L 3))) => (3)

; Note!

(L 3) => d
;but
(3 1 L) => (d)


you are confusing the (<offset> <length> L) syntax, which extracts a subsegment as a list with (L <index>), which extracts an element:


(set 'L '(a b c d e f g))

(3 1 L) => (d)  ; a list not element of L
(L 3) => d ; an element of L
(1 4 L) => (b c d e) ; a segment of L as a list
(L 4) => e


I suggest working through



http://www.newlisp.org/introduction-to-newlisp.pdf">http://www.newlisp.org/introduction-to-newlisp.pdf



to gain a basic understanding of lists and nested lists in LISP



and read this http://www.newlisp.org/downloads/newlisp_manual.html#indexing">http://www.newlisp.org/downloads/newlis ... l#indexing">http://www.newlisp.org/downloads/newlisp_manual.html#indexing



To clear up the difference between (<offset> <length> L) and (L <offset>) ;-)

lithper

#8
OK, the answer lies in the difference between

.....(1 1 list)  = sublist  .. (which is like a "slice") and

.....(list 1) = element



I see, thank you.  That makes sense.



..of course, I read those tutorial texts, but newbie questions are inevitable in any case, unfortunately.



.. and it might be the distinction (and whether the list search operators are constructed to be fed sublists and/or elements ) was not immediately obvious anyway.



So, the answer to the question
QuoteReference for functions like those from the "ref" family, "find" ... etc. - operators for work with lists - supposedly can take (list) as search arguments inside a bigger list (L)

is "no, they take only elements, no lists are allowed"



One case when element = (sublist) will only APPEAR TO LOOK as if it's a (list) as an argument, while in fact it works only as long as it functions as an element in the bigger list L that is being searched