1

I am trying to understand the function "substitute" in LISP, but there is something that I don't understand. When I perform this:

(defparameter *mytree* nil)
(push 1 *mytree*)
(substitute '8 '1 *mytree*)

Everything runs ok, the value of mytree is (8).

But, when I perform:

(defparameter *mytree* nil)
(push "A" *mytree*)
(substitute '8 '"A" *mytree*)

Then mytree is ("A") instead of (8) like I expect.

Any idea why this is happening?

Jordon Biondo
  • 3,974
  • 1
  • 27
  • 37
Xaving
  • 329
  • 1
  • 11
  • Is this actually a problem? You're getting `(8)` the first time because it substituted `'8` for `'1`. The second time, it substitutes `'8` for `'"A"`, so you're still getting the right answer. – Matthew Walton Mar 14 '14 at 13:50
  • 1
    possible duplicate of [Test if array is inside a list in lisp](http://stackoverflow.com/questions/19287777/test-if-array-is-inside-a-list-in-lisp) – sds Mar 14 '14 at 14:56
  • I didn't get the same result on the second example. – lurker Mar 15 '14 at 12:03
  • @matthew, sorry I made a mistake. I change it. – Xaving Mar 15 '14 at 15:47
  • @mbratch, substitution rely on eql to find the item to replace. and eql can behave differently, but as said by Jordon on sbcl implementation (eql "A" "A") return nil. – Xaving Mar 15 '14 at 15:51

1 Answers1

0

You need to use the correct equality checking method by using the :test keyword in substitute.

The signature for substitute is

(substitute newitem olditem sequence &key from-end test test-not start end count key)

Substitute is using eql by default, but that won't work in this scenario

(eql "A" "A") ;; nil
(equal "A" "A") ;; t

This will yield the correct results

(defparameter *mytree* nil)
(push "A" *mytree*)
(substitute 8 "A" *mytree* :test 'equal) ;; note the test, returns (8)
Svante
  • 50,694
  • 11
  • 78
  • 122
Jordon Biondo
  • 3,974
  • 1
  • 27
  • 37