how to access a value inside a nested structure - nested

I am having problems how do you access a definition inside a structure inside of a structure?
(define-struct health (maximum current))
;; A Health is a (make-health Nat Nat)
;; Requires:
;; current <= maximum
(define-struct weapon (strike-damage durability))
;; A Weapon is a (make-weapon Nat Health)
;; Requires:
;; strike-damage > 0
;; The Hero's rupee-total field is the total balance of rupees
;; (i.e., the in-game currency) possessed by the Hero
(define-struct hero (sword life rupee-total))
;; A Hero is a (make-hero Weapon Health Nat)
(define damaged-broadsword (make-weapon 5 (make-health 10 5)))
(define (total-damage sword)
(* (weapon-strike-damage sword) (weapon-durability sword)))
I am trying to multiply the current health of the sword with strike-damage
to do that I have to access durability, with has 2 values, maximum and current

You do it by nesting the accessors:
(define (total-damage sword)
(* (weapon-strike-damage sword)
(health-current (weapon-durability sword))))
Maybe more readable:
(define (total-damage sword)
(let* ((dmg (weapon-strike-damage sword)) ;; get damage value of sword
(h (weapon-durability sword)) ;; get sword's health-struct
(c (health-current h))) ;; get current health out of
(* dmg c))) ;; the health struct and calculate
;; so from your example:
(total-damage damaged-broadsword)
;; 25

Related

How to do looping in lisp?

Just started learning and coding lisp,
I'm trying to create a program that will continuously accept a number and stops only if and only if the last input number is twice the previous number.
Here's my code
----------
(let((a 0)
(b 0)
(count 0))
(loop
(= a b))
(princ"Enter Number: ")
(defvar a(read))
(format t "~% a = ~d" a)
(setq count (1+ count))
(while
(!= b(* a 2) || <= count 1)
(princ "Program Terminated Normally")
)
Thank you
a bit feedback
(let ((a 0)
(b 0)
(count 0))
(loop
(= a b)) ; here the LOOP is already over.
; You have a closing parenthesis
; -> you need better formatting
(princ"Enter Number: ")
(defvar a(read))
(format t "~% a = ~d" a)
(setq count (1+ count))
(while
(!= b(* a 2) || <= count 1)
(princ "Program Terminated Normally")
)
some improved formatting:
(let ((a 0)
(b 0)
(count 0))
(loop
(= a b)) ; LOOP ends here, that's not a good idea
(princ "Enter Number: ")
(defvar a(read)) ; DEFVAR is the wrong construct,
; you want to SETQ an already defined variable
(format t "~% a = ~d" a)
(setq count (1+ count))
(while ; WHILE does not exist as an operator
(!= b(* a 2) || <= count 1) ; This expression is not valid Lisp
(princ "Program Terminated Normally")
)
You may need to learn a bit more Lisp operators, before you really can write such loops. You also may want to use Lisp interactively and try out things, instead of trying to write code into an editor and never get feedback from a Lisp...
Here's an answer which definitely is not how you would do this in real life, but if you understand what it does you will understand one of the two big important things about Lisps.
(If you understand why the equivalent program would not work reliably in Scheme you'll also understand one of the important things about writing safe programs! Fortunately this is Common Lisp, not Scheme, so it's OK here.)
First of all let's write a little helper function to read integers. This is just fiddly detail: it's not important.
(defun read-integer (&key (prompt "Integer: ")
(stream *query-io*))
;; Read an integer. This is just fiddly details
(format stream "~&~A" prompt)
(values (parse-integer (read-line stream))))
OK, now here's a slightly odd function called mu (which stands for 'mutant U'):
(defun mu (f &rest args)
(apply f f args))
And now here is our program:
(defun read-integers-until-double-last ()
(mu (lambda (c getter current next factor)
(if (= next (* current factor))
(values current next)
(mu c getter next (funcall getter) factor)))
#'read-integer
(read-integer)
(read-integer)
2))
And here it is working:
> (read-integers-until-double-last)
Integer: 0
Integer: 4
Integer: 3
Integer: -2
Integer: -4
-2
-4
For extra mysteriosity you can essentially expand out the calls to mu here, which makes it either more clear or less clear: I'm not quite sure which:
(defun read-integers-until-double-last ()
((lambda (c)
(funcall c c
#'read-integer
(read-integer)
(read-integer)
2))
(lambda (c getter current next factor)
(if (= next (* current factor))
(values current next)
(funcall c c getter next (funcall getter) factor)))))
Again, this is not how you do it in real life, but if you understand what this does and how it does it you will understand quite an important thing about Lisps and their theoretical underpinnings. This is not all (not even most) of the interesting things about them, but it is a thing worth understanding, I think.

Is there an easy way to convert strings to variable names (identifiers) in Racket?

I am pretty new in Racket and I have tried to do something that is really easy in other languages, such as PHP, which is converting a string to a variable name.
Something like:
#lang racket
(define t0 3)
(display t0) ; It outputs 3
(define (symbol? (string->symbol "t1")) 2 )
(display t1) ; It would output 2, however it throws an error :(
Is there a way to convert a string to identifier? Because I need to define variable names from strings, dynamically.
You can do what you want with the help of namespaces. However look into hash tables first.
#lang racket
(define-namespace-anchor here)
(define ns (namespace-anchor->namespace here))
(define foo 42)
(parameterize ([current-namespace ns])
(namespace-variable-value (string->symbol "foo")))
The output of this program is 42.
Indeed soegaard hash tables are a very good solution, here is an example:
#lang racket
(define ht (make-hash))
(define sx "x")
(define sy "y")
(define sr "r")
(hash-set! ht sx 2)
(hash-set! ht sy 3)
(define r (+ (hash-ref ht sx) (hash-ref ht sy))) ;do calculation (+ 2 3)
(hash-set! ht sr r)
(hash-ref ht sr) ; it will output 5

How can I delete silence from the middle of .wav files in Audacity but not the edges?

I am trying to delete silence from an audio file using Audacity. There is a Nyquist plugin called Trim Silence which deletes silence from the start and end of a file, but not the middle. I would like to invert this, and delete silence from everywhere except the start and end.
I think the function below is the relevant part of the plugin. How should I change it to get a truncate-internal-silences function? (I don't know any Nyquist, or Lisp, so I'm struggling to understand what it currently does, let alone change it.)
Entirely different approaches also welcome - this is just my current best guess at how to edit my many audio files.
(defun trim-silence ()
;; Nyquist plug-ins cannot return 'no audio', so trap as error.
(if (< (get '*selection* 'peak-level) threshold)
(throw 'error (format nil "Error.~%All selected audio in the ~a selected track~%~
is below the silence threshold.~%~%~
Try setting the threshold to a~%~
lower (more negative) dB level."
(add-num-suffix (get '*track* 'index)))))
(if (> len (* limit *sound-srate*)) ;max length in samples
(throw 'error (format nil "Error.\nMax RAM usage by Trim Silence is set to ~a GB.~%This allows a maximum duration ~
for a ~a~%track at ~a Hz of ~a.~%Selected track is ~a.~%"
RAM-limit
(if (arrayp *track*) "stereo" "mono")
(round *sound-srate*)
(to-hhmmss limit)
(to-hhmmss (get-duration 1)))))
(let* (;; ratio provides tighter trimming for short selections
;; while maintaining reasonable speed for long selections
(ratio (max 10 (min 200 (round (/ len 100000.0)))))
(my-srate (/ *sound-srate* ratio))
(mysound (convert *track* ratio))
(limits (get-clip-limits)) ; (list start, end) times of audio clips
(clip-start (if (first limits)
(abs-to-relative-time (nth 0 limits)))) ; nil id invalid
(clip-end (if (second limits)
(abs-to-relative-time (nth 1 limits))))) ; nil if invalid
;loop through samples and mark start and end
(setf result (find-sil mysound clip-start clip-end))
(let ((start (if clip-start
(max clip-start
(- (/ (first result) my-srate) min-start-silence))
0))
(end (if clip-end
(min (+ (- (get-duration 1) (/ (second result) my-srate))
min-end-silence)
clip-end)
(get '*selection* 'end))))
;; ensure at least 1 sample remains
;; This should never happen.
(if (>= start end)
(setq start (- end (/ *sound-srate*))))
; trim
(multichan-expand #'extract-abs start end (cue *track*)))))

Parameter declaration List. should be a vector in Clojure [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I'm trying to do my CS lab for my class, but every time I try running my tests vs. my code, my code never loads up. It shows the following error:
Exception in thread "main" java.lang.IllegalArgumentException: Parameter declaration List. should be a vector
at clojure.core$assert_valid_fdecl.invoke(core.clj:6567)
at clojure.core$sigs.invoke(core.clj:220)
at clojure.core$defn.doInvoke(core.clj:294)
at clojure.lang.RestFn.invoke(RestFn.java:494)
at clojure.lang.Var.invoke(Var.java:431)
at clojure.lang.AFn.applyToHelper(AFn.java:178)
at clojure.lang.Var.applyTo(Var.java:532)
at clojure.lang.Compiler.macroexpand1(Compiler.java:6366)
at clojure.lang.Compiler.macroexpand(Compiler.java:6427)
at clojure.lang.Compiler.eval(Compiler.java:6495)
at clojure.lang.Compiler.load(Compiler.java:6952)
at clojure.lang.RT.loadResourceScript(RT.java:359)
at clojure.lang.RT.loadResourceScript(RT.java:350)
at clojure.lang.RT.load(RT.java:429)
Here is my code sorry guys. I have no idea what is wrong, everything looks right to me.
(ns linked_list_lab.core)
;; We start with a defrecord. In traditional lisps, the
;; first element of a list is called the "car", standing for
;; "Contents of Address Register," the name of the register where
;; it was stored. The pointer to the rest of the list was called
;; the "cdr," for "Contents of Decrement Register", and is pronounced
;; "could-er".
(defrecord Cons [car cdr])
;; One problem with singly linked lists is that finding the length is
;; expensive $${\cal O}(n)$$. We can use a wrapper class to deal with
;; that. Here we have a `List` record that keeps a pointer to the list
;; along with the size.
(defrecord List [data size])
;; The `make-list` function just creates an empty list.
(defn make-list
"Create an empty list."
(List. nil 0))
;; The `insert-front` function shows a special syntax Clojure has.
;; If you know the argument to your function should be a record or a
;; hash-map, you can use this pattern-matching syntax as a shorthand.
;; Here we have `{:keys [data size]}`, which will create new variables
;; `data` and `size`. So if I pass in `{:data 10 :size 20}`, then
;; `data` will be given 10, and `size` will be given 20.
;; This is often called "destructuring".
;; Test broke-1 will not increment the size.
;; Test broke-2 will forget to do the cons.
;; Test broke-3 will replace the cons and not point to the next one.
(defn insert-front
"Insert an element at the beginning of the list."
[{:keys [data size]} new-elt]
(List. (Cons. new-elt data) (+ 1 size)))
;; Here are some utility functions that convert Clojure lists to
;; our Cons. record, and vice-versa. The broke versions will not
;; mess with these.
(defn list-to-cons
[xx]
(cond (empty? xx) nil
:else (Cons. (first xx) (list-to-cons (next xx)))))
(defn cons-to-list
[xx]
(cond (nil? xx) '()
:else (cons (:car xx) (cons-to-list (:cdr xx)))))
;; The `insert-sorted` function assumes that the elements are orderable
;; and puts the element in the spot that will preserve the ordering.
;; Test broke-4 will use `(Cons. elt (:cdr xx))` in the third case.
;; Test broke-5 will use `(Cons. (:car xx) nil)` in the second case.
(defn insert-ordered-cons
"Insert the element `elt` into an ordered `Cons.` chain.
This is used by `insert-ordered`."
[elt xx]
(cond (empty? xx) (Cons. elt nil)
(> elt (:car xx)) (Cons. (:car xx) (insert-ordered-cons elt (:cdr xx)))
:fine-be-that-way (Cons. elt xx)))
(defn insert-ordered
"Insert an element into an ordered list."
[{:keys [data size]} new-elt]
(List. (insert-ordered-cons new-elt data) (+ size 1)))
;; The `delete` function will delete one element from the list.
;; Test broke-6 will truncate the list past the deletion point.
;; Test broke-7 will forget to decrement the size.
;; Test broke-8 will always decrement the size, even if the element is not found.
(defn delete
"Delete `elt` from `xx`."
[elt xx]
(cond (empty? xx) nil
(= elt (:car xx)) (:cdr xx)
:else (Cons. (:car xx) (delete elt (:cdr xx))) )
)
;; The `delete-all` function will delete all copies of elt from xx.
;; Test broke-9 will delete only one copy.
;; Test broke-10 will decrement the count instead of properly subtracting the
;; number of deletions.
(defn delete-all
"Delete all occurrences of `elt` from `xx`."
[elt xx]
(cond (empty? xx) nil
(= elt (:car xx)) (delete-all elt (:cdr xx))
:else (Cons. (:car xx) (delete-all elt (:cdr xx)))
)
)
The function make-list misses a parameter declaration vector.
(defn make-list
[] ;; <- fix
...)
You are doing a defn without a parameter list.

Define struct with one field in scheme

I am working on a homework assignment for a class. The problem statement says to use the data definition:
(define-struct diff-exp exprs)
(define-struct mult-exp exprs)
;; An Expr is one of
;; -- Number
;; -- (make-diff-exp (cons Expr LOExpr))
;; -- (make-mult-exp (cons Expr LOExpr))
;; Interpretation: a diff-exp represents a difference,
;; and a mult-exp represents a multiplication.
;; A List of Exprs (LOExpr) is one of
;; -- empty
;; -- (cons Expr LOExpr)
However, when I have just that in the source, Dr. Scheme (Intermediate Student Language) says:
define-struct: expected a sequence of field names after the structure type name in `define-struct', but found something else
Is there something I am missing here or did my teacher give me an invalid data definition?
Like Anon suggested in the comment above, define-struct takes a list of fields; if you need only one, then use a list of one element. Example code:
(define-struct diff-exp (exprs))
(let ((myexpr (make-diff-exp (list foo bar))))
(diff-exp-exprs myexpr))
You can rifle through the many sundry features of define-struct in the PLT Scheme documentation.

Resources