splitting up a string

  • (2 Pages)
  • +
  • 1
  • 2

20 Replies - 3723 Views - Last Post: 31 January 2013 - 09:41 PM

#16 NecroWinter  Icon User is offline

  • D.I.C Regular

Reputation: 35
  • View blog
  • Posts: 318
  • Joined: 21-October 11

Re: splitting up a string

Posted 31 January 2013 - 08:33 AM

Okay, so I think I have the labels definition correct, I am not getting errors. However, a new issue creeps up, When I call DC nothing seems to be happening. Im sorry to keep having issues, but LISP just doesnt like me haha. Once I get this done im sure ill have a much better understanding of it. But can you take a look at this code, and possibly tell me why nothing is happening?

input:(split "To iterate is human, to recurse divine!" " ,!")
response: NIL


(defun split (str delim)
 (labels ((toList (str number) 
 
	    (if 
	    (or (null str) (= number (length str))) 
	    nil 
	    (cons(subseq str number (+ number 1))(toList str (+ 1 number)) ))  
    
 
 
 
 )
 
	  (dC (l1 delim str)
 
 
	    (if (or (null l1) (null delim)) 
	    nil 
	    (if (member (car l1) delim) 
	    (cons str (dC (cdr l1) delim nil)) 
	    (dC (cdr l1) delim (concatenate 'string str (string (car l1))))))
 
 
 
 
 
 )
 ) 
 
 
 
 
 

     (dc (tolist str 0) (tolist delim  0 ) nil)
     )
     
     )



This post has been edited by NecroWinter: 31 January 2013 - 08:35 AM

Was This Post Helpful? 0
  • +
  • -

#17 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2087
  • View blog
  • Posts: 3,175
  • Joined: 21-June 11

Re: splitting up a string

Posted 31 January 2013 - 09:57 AM

You changed your toList function to return a list of strings rather than characters. That's fine, but the problem with strings is that they can't be compared using the eql function while characters can. (Basically eql acts like == does in Java). To compare strings with each other, you need to use the equalp function.

By default the member function uses eql to compare the elements of the list. So in your case, your if condition using member will always be false because member uses eql and eql always counts your strings as unequal because they aren't references to the same string in memory.

You can fix this by adding the keyword argument :test #'equalp to the call to member (which tells member to use the equalp function instead of eql - equalp works fine with strings) or by changing your toList function back to produce a list of chars rather than strings.
Was This Post Helpful? 2
  • +
  • -

#18 NecroWinter  Icon User is offline

  • D.I.C Regular

Reputation: 35
  • View blog
  • Posts: 318
  • Joined: 21-October 11

Re: splitting up a string

Posted 31 January 2013 - 12:50 PM

Thats strange, I don't recall changing anything. But you're right, it did return a list of strings. So I changed the code this time to make sure it gave me a list of characters. So if I run the code, just to make sure that "toList" is in fact giving me characters, I can do the following:

in: (split "hello" "")
out: (#\h #\e #\l #\l #\o)
(defun split (str delim)
 (labels ((toList (str number) 
 
	    (if 
	    (or (null str) (= number (length str))) 
	    nil 
	    ;(cons(coerce(subseq str number (+ number 1)) 'character)(toList str (+ 1 number))))  
	    (cons (char str number) (toList str (+ 1 number))))
 
 
 
 )
 
	  (dC (l1 delim str)
 
 
	    (if (or (null l1) (null delim)) 
	    nil
	    (if (member (car l1) delim) 
	    (cons str (dC (cdr l1) delim nil)) 
	    (dC (cdr l1) delim (concatenate 'string str (string (car l1))))))
 
 
 
 
 
 )
 ) 
 
 
 
 
 

     ;(dc (tolist str 0) (tolist delim  0 ) nil)
     (toList str 0)
     )
     
     )


So, now when I try the following code (the following code actually executes DC unlike the code above)

(defun split (str delim)
 (labels ((toList (str number) 
 
	    (if 
	    (or (null str) (= number (length str))) 
	    nil 
	    ;(cons(coerce(subseq str number (+ number 1)) 'character)(toList str (+ 1 number))))  
	    (cons (char str number) (toList str (+ 1 number))))
 
 
 
 )
 
	  (dC (l1 delim str)
 
 
	    (if (or (null l1) (null delim)) 
	    nil
	    (if (member (car l1) delim) 
	    (cons str (dC (cdr l1) delim nil)) 
	    (dC (cdr l1) delim (concatenate 'string str (string (car l1))))))
 
 
 
 
 
 )
 ) 
 
 
 
 
 

     (dc (tolist str 0) (tolist delim  0 ) nil)
     ;(toList str 0)
     )
     
     )
     




(split "hello" "l")
("he" NIL)


I don't know why its doing this, I think its related to my dC function at this point. Oddly enough, when I made this code within "defun" functions, I was able to get results that I expected, but when I convert to local functions its not the same. Im going to keep looking, but if you notice anything about my dC function that would cause this bug, please let me know

This post has been edited by NecroWinter: 31 January 2013 - 12:55 PM

Was This Post Helpful? 0
  • +
  • -

#19 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2087
  • View blog
  • Posts: 3,175
  • Joined: 21-June 11

Re: splitting up a string

Posted 31 January 2013 - 09:00 PM

One thing I noticed: In toList your null str can never be true (because null works on lists, not strings and simply never returns true for strings) and is also completely unnecessary. If the string is empty the condition (= number (length str)) will be true anyway, so you don't need the other condition.

There's also no point in checking whether delim is empty in the dC method. The only way delim could be nil is if the user passed in an empty string as the delimiter to the split function. If that happens, I'd argue the correct result would be to return a list containing the whole string, not nil. I.e. (split "hello" "") should return ("hello"), not NIL. Same as if you passed in a delimiter that doesn't appear in the string. Incidentally that's the behavior you get if you simply remove the check whether delim is empty.

These points have nothing to do with your problem, but I thought I'd mention them anyway.

This post has been edited by sepp2k: 31 January 2013 - 09:04 PM

Was This Post Helpful? 1
  • +
  • -

#20 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2087
  • View blog
  • Posts: 3,175
  • Joined: 21-June 11

Re: splitting up a string

Posted 31 January 2013 - 09:15 PM

View Postsepp2k, on 01 February 2013 - 05:00 AM, said:

I.e. (split "hello" "") should return ("hello"), not NIL. Same as if you passed in a delimiter that doesn't appear in the string. Incidentally that's the behavior you get if you simply remove the check whether delim is empty.


Which is to say, it would be the behavior if the function were working correctly. And this brings us to the problem: When you reach the end of the string, you return the empty list. So the value of str (which contains everything since the last time you've found a delimiter) will simply be discarded. That's why the "o" is missing from your result. You need to change it to return a list containing str rather than nil.

Once you did that, the result will be ("he" NIL "o"). Why the NIL in the middle? Because "hello" is split into three parts: the part before the first l, the part between the two ls and the part after the last l. Since the part between the two ls is empty, you get back a str that's never been appended to, i.e. you get back the initial value you pass in for str in the recursive call where you start with a new string. And that value is NIL.

If you use "" instead of NIL in the two places where you call dC with NIL as the third argument, you'll get back ("he" "" "o") as the result. Since that's what most split functions would return for that input, that should be the correct result.
Was This Post Helpful? 1
  • +
  • -

#21 NecroWinter  Icon User is offline

  • D.I.C Regular

Reputation: 35
  • View blog
  • Posts: 318
  • Joined: 21-October 11

Re: splitting up a string

Posted 31 January 2013 - 09:41 PM

View Postsepp2k, on 31 January 2013 - 09:15 PM, said:

View Postsepp2k, on 01 February 2013 - 05:00 AM, said:

I.e. (split "hello" "") should return ("hello"), not NIL. Same as if you passed in a delimiter that doesn't appear in the string. Incidentally that's the behavior you get if you simply remove the check whether delim is empty.


Which is to say, it would be the behavior if the function were working correctly. And this brings us to the problem: When you reach the end of the string, you return the empty list. So the value of str (which contains everything since the last time you've found a delimiter) will simply be discarded. That's why the "o" is missing from your result. You need to change it to return a list containing str rather than nil.

Once you did that, the result will be ("he" NIL "o"). Why the NIL in the middle? Because "hello" is split into three parts: the part before the first l, the part between the two ls and the part after the last l. Since the part between the two ls is empty, you get back a str that's never been appended to, i.e. you get back the initial value you pass in for str in the recursive call where you start with a new string. And that value is NIL.

If you use "" instead of NIL in the two places where you call dC with NIL as the third argument, you'll get back ("he" "" "o") as the result. Since that's what most split functions would return for that input, that should be the correct result.


...

I think we got it lol

lots of reps coming your way =)

I cant thank you enough
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2