follow up How to generate arbitrary waveforms

Using Nyquist scripts in Audacity.
Post and download new plug-ins.
Forum rules
If you require help using Audacity, please post on the forum board relevant to your operating system:
Windows
Mac OS X
GNU/Linux and Unix-like
steve
Site Admin
Posts: 49026
Joined: Sat Dec 01, 2007 11:43 am
Operating System: Linux *buntu

Re: follow up How to generate arbitrary waveforms

Post by steve » Wed Jan 17, 2018 4:43 pm

Nyquist is very similar to LISP, in fact it is an extended version of XLISP.
LISP is a very old computer language and there are many "dialects" which have subtle differences.

You can find the manual for XLISP here: http://www.audacity-forum.de/download/e ... -index.htm
This version of the manual also includes a few notes about Nyquist for the (few) cases where Nyquist differs from XLISP.

The diference between LET and LET* is that the latter evaluates the bindings in sequential order, whereas without the "*" the bindings are made in no particular order.

Here is a common error that can occur when using LET

Code: Select all

(setq x 3)
(let ((y (+ 2 x))
      (z (* 2 y)))
  (print x)
  (print y)
  (print z))
In this case Nyquist / LISP raises an error:

Code: Select all

error: unbound variable - Y
The reason for the error is that the two bindings (y (+ 2 x)) and (z (* 2 y)) are not performed sequentially, so when LISP comes to evaluate Z, it can't because Y has not yet been evaluated.

The correct way to write the above is to use LET* so that LISP will first evaluate Y as (+ 2 x), and then evaluate Z as (* 2 y).

Code: Select all

(setq x 3)
(let* ((y (+ 2 x))
      (z (* 2 y)))
  (print x)
  (print y)
  (print z))
which prints:

Code: Select all

3
5
10
and returns the final value 10.

The code example that you gave is a little confusing, but similar to my example above.

You have used LET, so the bindings are not performed sequentially.
LISP will evaluate (a 'inside) by setting the value of A to 'inside.

If you had used LET*, then the next binding (b a) would have set the value of B to 'inside [sequential evaluation], but you didn't, so LISP can't do that. What happens instead is that LISP looks for a value of A that it can use, and finds one in the global scope (outside of the LET form). So B is set to the value 'top.

When LISP gets down to the final line, it replaces the first ~S with the first evaluation of A that it can find, which is the variable inside the LET form, which is 'inside.
The second ~S takes the value of B, which is 'top
The third ~S takes the value returned by (dummy-function).

(dummy function) looks for a value for A, and finds it in the global scope, which is where it was set to 'top.

So here's your code, properly formatted, with comments added:

Code: Select all

(setq a 'top) ; Global scope. A = 'top

(defun dummy-function ()
  "Function returns global value of A"
  a)

(let ((a 'inside) ; Local binding of A to 'inside
      (b a))      ; Local binding of B to the global value of A   
  (format nil "~S ~S ~S" a b (dummy-function))) 
9/10 questions are answered in the FREQUENTLY ASKED QUESTIONS (FAQ)

Post Reply