Nyquist does not appear to have a function for substituting characters in a string, so here’s a function to do just that.
;; substitute character in string
(defun subst-char-string (string old new)
(setq newstring "") ; initialise the new string
(dotimes (i (length string))
(let ((ch (char string i))) ; ch is the next character in the string
(if (char= ch old)(setq ch new))
(setq newstring (strcat newstring (string ch))))) ; add character to string
newstring)
(print (subst-char-string "Hello World" '#space '- ))
I’m quite sure you know, but the function above pollutes the global namespace by creating a global variable named “newstring”, it would be better to make “newstring” al local “let” variable. Here is what I usually write:
(defmacro string-append (variable &rest strings)
`(setq ,variable (strcat ,variable ,@strings)))
(defun subst-char-string (string old-char new-char)
(cond ((not (stringp string))
(error "subst-char-string: not a string" string))
((not (characterp old-char))
(error "subst-char-string: not a character" old-char))
((not (characterp new-char))
(error "subst-char-string: not a character" new-char))
(t
(let ((end (length string))
(result ""))
(dotimes (index end)
(let ((current-char (char string index)))
(if (char= old-char current-char)
(string-append result (string new-char))
(string-append result (string current-char)))))
result))))
(print (subst-char-string "Hello World" #space #-)) => "Hello-World"
The local “end” variable is not really necessary, because “dotimes” pre-evaluates its termination-test value and stores it in an internal local variable, but with more complicated “dotimes” loops the “end” variable makes the code more readable [at least for me].
BTW: The unicode research says: (char ) is safe with multi-byte unicode characters.
Good point re. ‘newstring’ being a global variable.
I’m a bit cautious about creating functions that depend on other functions/macros as it seems a bit too easy to forget about the dependency. For short functions I generally prefer to nest the dependant function to ensure that they stay together (unless of course the function/macro is also used elsewhere). Is there anything wrong with this approach?
(defun subst-char-string (string old-char new-char)
; nested macro
(defmacro string-append (variable &rest strings)
`(setq ,variable (strcat ,variable ,@strings)))
; back to main function code
(let ((end (length string))
(result ""))
(dotimes (index end)
(let ((current-char (char string index)))
(if (char= old-char current-char)
(string-append result (string new-char))
(string-append result (string current-char)))))
result))
(print (subst-char-string "Hello World" '#space '#-)) ; => "Hello-World"
or simply:
(defun subst-char-string (string old new)
(let ((newstring "")) ; initialise the new string
(dotimes (i (length string))
(let ((ch (char string i))) ; ch is the next character in the string
(if (char= ch old)(setq ch new))
(setq newstring (strcat newstring (string ch))))) ; add character to string
newstring))
(print (subst-char-string "Hello World" '#space '#- )) ; =>Hello-World
Of course there’s nothing wrong. The “string-append” is a simplified version of one of my standard text macros and I just simply was to lazy to fiddle it into the function’s code, that’s all [sorry if you had expexted more secret science behind that ] …
I’ve just been reading about functions in the xlisp manual - it looks like an another alternative would be to make ‘newstring’ a local variable by including it as &aux argument in the function, for example:
(defun subst-char-string (string old new &aux (newstring ""))
(dotimes (i (length string))
(let ((ch (char string i))) ; ch is the next character in the string
(if (char= ch old)(setq ch new))
(setq newstring (strcat newstring (string ch))))) ; add character to string
newstring)
I don’t recall ever seeing this method used in any plug-ins, but it looks like a neat way to set local variables if there are only a few.
That’s correct.
This is a very old topic, and I guess that during one of the forum updates over the years, the backslashes got lost in the forum’s database. I don’t think these code samples would have ever worked without the backslashes.