starts-with question

Started by johnd, October 07, 2008, 10:25:05 AM

Previous topic - Next topic

johnd

starts-with now takes a list and expression as an argument.  For example:



> (starts-with '((1 2) 3 4) '(1 2))  -->  true



What is the logic for limiting this to just the first element?  Doing so makes this little more than syntactic sugar for



> (= (first '((1 2) 3 4)) '(1 2))  --> true



Could this instead be a sublist match rather than membership so that the following would be true?



(starts-with '((1 2) 3 4) '((1 2) 3))



This one is more difficult to implement, but it can be done as follows:



> (set 'arg1 '((1 2) 3 4))

((1 2) 3 4)

> (set 'arg2 '((1 2) 3))

((1 2) 3)

> (= (0 (length arg2) arg1) arg2)

true

>



This could pose problems if implicit slicing out of bounds generates an error (it doesn't currently, but then neither did implicit indexing out of bounds not too long ago).  Just imagine arg2 is longer than arg1.  Also, things get more complicated with the corresponding ends-with version.

 

Broadly speaking, I am advocating support for sublist evaluations as well as membership/containment evaluations.  This can get tricky when the potential sublist is situated below the first level of the list, but ultimately the judgment would be the same as for membership of an element.



Thanks,



John

Lutz

#1
Using 'starts-with' that way would create ambiguities, because ((1 2) 3) would match ((1 2) 3 4) with segment slicing but also would match (((1 2) 3) 5 6) as first sublist element.



but you could use 'match' for this:


(match '((1 2) 3 *) '((1 2) 3 4))

'match' would allow you any complexity in your search pattern, similar to regular expressions.

johnd

#2
Lutz,



Thank for your quick reply.



The ambiguity you mention is a serious one and it would have to be resolved somehow.  Perhaps an additional argument to flag one or the other form.  However, it's even more serious when you consider the list might contain both the sublist and the element.



I'm a little bit new to match but it looks interesting.  To extend your example to one using variables, would I have to push a * onto the end of the list variable?



Thanks,



John

cormullion

#3
How about these?


(println (match '((1 2) 3 *) '((1 2) 3 4)))
;-> ((4))

(set 'lk4  '((1 2) 3 *))
(println (match lk4 '((1 2) 3 4)))
;-> ((4))

(set 'lk4 '((1 2) 3))
(push '* lk4 -1)
(println (match lk4 '((1 2) 3 4)))
;-> ((4))

(set 'lk4 '((1 2) 3))
(println (match (append lk4 '(*)) '((1 2) 3 4)))
;-> ((4))