Using Nyquist scripts in Audacity.
Post and download new plug-ins.
-
steve
- Site Admin
- Posts: 81653
- Joined: Sat Dec 01, 2007 11:43 am
- Operating System: Linux *buntu
Post
by steve » Fri Oct 29, 2010 7:34 pm
Nyquist does not appear to have a function for substituting characters in a string, so here's a function to do just that.
Code: Select all
;; 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 '- ))
-
edgar-rft
- Posts: 347
- Joined: Sun Jan 20, 2008 12:03 am
- Operating System: Please select
Post
by edgar-rft » Sat Oct 30, 2010 3:26 am
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:
Code: Select all
(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 <string> <index>) is safe with multi-byte unicode characters.
- edgar
-
steve
- Site Admin
- Posts: 81653
- Joined: Sat Dec 01, 2007 11:43 am
- Operating System: Linux *buntu
Post
by steve » Sat Oct 30, 2010 1:08 pm
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?
Code: Select all
(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:
Code: Select all
(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
-
edgar-rft
- Posts: 347
- Joined: Sun Jan 20, 2008 12:03 am
- Operating System: Please select
Post
by edgar-rft » Sat Oct 30, 2010 5:19 pm
stevethefiddle wrote: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?
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

] ...
- edgar
-
steve
- Site Admin
- Posts: 81653
- Joined: Sat Dec 01, 2007 11:43 am
- Operating System: Linux *buntu
Post
by steve » Sun Oct 31, 2010 9:33 pm
edgar-rft wrote: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.
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:
Code: Select all
(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.
-
agua
- Posts: 127
- Joined: Wed Mar 14, 2018 3:15 am
- Operating System: Windows 7
Post
by agua » Thu Jul 18, 2019 7:28 pm
Hi Steve and Edgar. Using any of those code versions for the substitution, I'm getting an error. Any idea what I am doing wrong ?
Here is the following error in Debug window :
error: illegal character after # - 115
Function: #<Subr-(null): #13c0c840>
Arguments:
#<File-Stream: #4823f68>
#\#
Function: #<Subr-(null): #13c0c800>
Arguments:
#<File-Stream: #4823f68>
#\(
Function: #<Subr-(null): #13c0c800>
Arguments:
#<File-Stream: #4823f68>
#\(
1> error: unbound variable - PACE
if continued: try evaluating symbol again
Function: #<Subr-(null): #13c0c840>
Arguments:
#<File-Stream: #4823f68>
#\#
Function: #<Subr-(null): #13c0c800>
Arguments:
#<File-Stream: #4823f68>
#\(
Function: #<Subr-(null): #13c0c800>
Arguments:
#<File-Stream: #4823f68>
#\(
2> error: illegal character after # - 45
Function: #<Subr-(null): #13c0c840>
Arguments:
#<File-Stream: #4823ee8>
#\#
Function: #<Subr-(null): #13c0c840>
Arguments:
#<File-Stream: #4823f68>
#\#
Function: #<Subr-(null): #13c0c800>
Arguments:
#<File-Stream: #4823f68>
#\(
Function: #<Subr-(null): #13c0c800>
Arguments:
#<File-Stream: #4823f68>
#\(
3> error: misplaced right paren
Function: #<Subr-(null): #13c0c7e0>
Arguments:
#<File-Stream: #4823ee8>
#\)
Function: #<Subr-(null): #13c0c840>
Arguments:
#<File-Stream: #4823ee8>
#\#
Function: #<Subr-(null): #13c0c840>
Arguments:
#<File-Stream: #4823f68>
#\#
Function: #<Subr-(null): #13c0c800>
Arguments:
#<File-Stream: #4823f68>
#\(
Function: #<Subr-(null): #13c0c800>
Arguments:
#<File-Stream: #4823f68>
#\(
4> error: misplaced right paren
Function: #<Subr-(null): #13c0c7e0>
Arguments:
#<File-Stream: #4823ee8>
#\)
Function: #<Subr-(null): #13c0c7e0>
Arguments:
#<File-Stream: #4823ee8>
#\)
Function: #<Subr-(null): #13c0c840>
Arguments:
#<File-Stream: #4823ee8>
#\#
Function: #<Subr-(null): #13c0c840>
Arguments:
#<File-Stream: #4823f68>
#\#
Function: #<Subr-(null): #13c0c800>
Arguments:
#<File-Stream: #4823f68>
#\(
Function: #<Subr-(null): #13c0c800>
Arguments:
#<File-Stream: #4823f68>
#\(
5> 4> 3> 2> 1>
-
agua
- Posts: 127
- Joined: Wed Mar 14, 2018 3:15 am
- Operating System: Windows 7
Post
by agua » Thu Jul 18, 2019 7:34 pm
OK, I think I found the trouble. Everything went fine when I change #space and #- by #\space and #\-.
-
steve
- Site Admin
- Posts: 81653
- Joined: Sat Dec 01, 2007 11:43 am
- Operating System: Linux *buntu
Post
by steve » Thu Jul 18, 2019 7:59 pm
agua wrote: ↑Thu Jul 18, 2019 7:34 pm
OK, I think I found the trouble. Everything went fine when I change #space and #- by
#\space and
#\-.
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.