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.
Related
Imagine I have a function that receive a array of structs like this:
(defun name-of-func (array)
(dotimes (i (array-total-size array))
(print (aref array i))))
and the stuct is something like this
(defstruct sTSP
cidade
x
y)
How can I access the field x on i position of the array?
Please take a look at the definition of defstruct.
It is long, but well worth the read.
If you are lazy, like we all are, search for reader:
(defstruct foo x y z)
(defparameter foo (make-foo :x 2 :y 4))
(foo-x foo)
==> 2
(foo-y foo)
==> 4
(foo-z foo)
==> NIL
PS1. Please note that array-total-size should
not be used with aref but
rather with row-major-aref.
The difference is with multi-dimensional arrays which are implemented
as vectors under the hood.
E.g., your function will fail on (make-array '(2 2) :initial-element (make-sTSP)).
PS2. I re-use foo for both type name and variable name to illustrate that they reside is different name spaces.
(setq a '("bar" "baz" "barz"))
(setq prefix "foo")
;; Expected result
==> ("foobar" "foobaz" "foobarz")
I have been doing this by dolist or iterating through car. Is there a single function doing the same job?
Not a single function, but I would use:
(mapcar (apply-partially #'concat prefix) a)
There are lots of ways you could do this, though, and there's probably nothing particularly wrong with what you were doing.
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.
I need some function which among other stuff would define a new global symbol. So that I could use it like this:
(define (func-prototype symbol value comment)
(define symbol value) ; this should somehow be reformulated
(format "~a=~a !~a\n" symbol value comment))
(define string-list (map func-prototype
'((s1 1 "first value")
(s2 20 "second value")
(s3 300 "third value))))
and be able to get the following results:
> string-list
'("s1=1 !first value\n"
"s2=20 !second value\n"
"s3=300 !third value\n")
> s1
1
> s2
20
> s3
300
Can this be implemented as a function or it is possible to do that only with the help of macros? Could you please suggest any possible implementations or at least give some hints/references that might be helpful?
I'd rethink the general approach, making it simpler. My suggestion: define a global hash table and inside the function add bindings to it, for example:
(define value-map (make-hash))
(define (func-prototype symbol value comment)
(hash-set! value-map symbol value)
(format "~a=~a !~a\n" symbol value comment))
Use it like this:
(define string-list
(map (lambda (lst)
(apply func-prototype lst))
'((s1 1 "first value")
(s2 20 "second value")
(s3 300 "third value"))))
string-list
=> '("s1=1 !first value\n"
"s2=20 !second value\n"
"s3=300 !third value\n")
And wherever you need to refer to one of the symbols in the hash table, do this:
(define (get key)
(hash-ref value-map key))
(get 's1)
=> 1
(get 's2)
=> 20
(get 's3)
=> 300
In general it is not possible to accomplish what you are trying to accomplish in the way you described. Your only hope would be to write stuff out to a file and then load that file into an interactive session. But even then.
In scheme you can't introduce top-level names, such as your desired s1, s2, and s3, except at the top-level. To do so, you could define a macro as:
>(define-syntax define-foo
(syntax-rules ()
((_ name value)
(define name value))))
>(define-foo s1 1)
<undefined>
> s1
1
If you try to use that macro in a function, it is no dice because the body of a function must end with an expression and any definition forms, like what the above macro would expand into, become local variables. That is:
(define (func-prototype name value comment)
(define-foo name value)
name)
>(func-prototype 's1 1 "com")
1
> s1
<error>
One approach that you could take that would work if your string-list is a constant would be as such:
> (define-syntax declare-variables
(syntax-rules ()
((_ (name value comment) ...)
(begin
(define name value)
...))))
> (declare-variables (s1 1 "com") (s2 20 "com") (s3 300 "com"))
> s1
1
This gets it done (I've ignored using 'comment') but, as I said, requires a compile time string-list.
One possibility you might think would work, but wouldn't, would be to use eval as:
(eval '(define s1 1) (environment ...))
but 'eval' only works for expressions, not declarations. Which gets me back to 'load' as a possibility.
First, consider whether you really want to do this, or whether a different solution (like a hash table) would work as well.
You can do this with reflection and dynamic evaluation using the eval procedure.
;; define-variable-with-value! : symbol any -> void
(define (define-variable-with-value! name value)
(eval `(define ,name (quote ,value))))
The quote is important; otherwise you risk reinterpreting a value as an expression to evaluate. To see the difference, consider the example
(define-variable-with-value! 'x (list 'error "kaboom"))
When defining a struct type and instance, I can print the value and get the "struct" implementation type:
(defstruct person :name :age)
(def p (struct person "peter" 30))
user=> p
{:name "peter", :age 30}
user=> (type p)
clojure.lang.PersistentStructMap
But is it possible to tell whether p is an instance of the struct type "person"?
See: this post in the Clojure Google Group.
In general the group archives are a treasure chest...
Note: The functionality of structs is replaced by records. Then this is not a problem anymore, because records really define new type and you can check with instance? whether something is of record of a certain type.
A bit ugly, but it works:
(require '[clojure.contrib.java-utils :as cj])
(defn struct-instance? [struct-def sm]
(= (cj/wall-hack-field clojure.lang.PersistentStructMap "def" sm)
struct-def))
(struct-instance? person p)
; => true
(struct-instance? person (conj p [:foo 1] [:bar 2]))
; => true
(defstruct foo :k1 :k2)
(struct-instance? foo p)
; => false
Stuff from clojure.contrib.java-utils will be available in 1.2 in part in clojure.java, in part in clojure.contrib.java (I guess?), and also in clojure.contrib.java-utils for backward compatibility... Although the details might still change. At any rate, Meikel is right about defrecord replacing defstruct, so if you're working on 1.2, prefer that.