I am trying to create a dictionary or hash-table where keys are string and values are integers with following code:
(define dict #())
(dict-set! dict "bash" 1)
(displayln dict)
(dict-set! dict "racket" 1)
(displayln dict)
However, it gives following error:
dict-set!: contract violation
expected: (dict-implements/c dict-set!)
given: '#()
in: the d argument of
(->i
((d (dict-implements/c dict-set!))
(k (d) (dict-key-contract d))
(value (d) (dict-value-contract d)))
(_r void?))
contract from: <collects>/racket/dict.rkt
Where is the problem and how can it be solved?
The problem is that the literal #() is an empty vector.
To make a mutable hash table, use (make-hash).
(define dict (make-hash))
Related
I'm studying Standard ML and one of the exercices I have to do is to write a function called opPairs that receives a list of tuples of type int, and returns a list with the sum of each pair.
Example:
input: opPairs [(1, 2), (3, 4)]
output: val it = [3, 7]
These were my attempts, which are not compiling:
ATTEMPT 1
type T0 = int * int;
fun opPairs ((h:TO)::t) = let val aux =(#1 h + #2 h) in
aux::(opPairs(t))
end;
The error message is:
Error: unbound type constructor: TO
Error: operator and operand don't agree [type mismatch]
operator domain: {1:'Y; 'Z}
operand: [E]
in expression:
(fn {1=1,...} => 1) h
ATTEMPT 2
fun opPairs2 l = map (fn x => #1 x + #2 x ) l;
The error message is: Error: unresolved flex record (need to know the names of ALL the fields
in this context)
type: {1:[+ ty], 2:[+ ty]; 'Z}
The first attempt has a typo: type T0 is defined, where 0 is zero, but then type TO is referenced in the pattern, where O is the letter O. This gets rid of the "operand and operator do not agree" error, but there is a further problem. The pattern ((h:T0)::t) does not match an empty list, so there is a "match nonexhaustive" warning with the corrected type identifier. This manifests as an exception when the function is used, because the code needs to match an empty list when it reaches the end of the input.
The second attempt needs to use a type for the tuples. This is because the tuple accessor #n needs to know the type of the tuple it accesses. To fix this problem, provide the type of the tuple argument to the anonymous function:
fun opPairs2 l = map (fn x:T0 => #1 x + #2 x) l;
But, really it is bad practice to use #1, #2, etc. to access tuple fields; use pattern matching instead. Here is a cleaner approach, more like the first attempt, but taking full advantage of pattern matching:
fun opPairs nil = nil
| opPairs ((a, b)::cs) = (a + b)::(opPairs cs);
Here, opPairs returns an empty list when the input is an empty list, otherwise pattern matching provides the field values a and b to be added and consed recursively onto the output. When the last tuple is reached, cs is the empty list, and opPairs cs is then also the empty list: the individual tuple sums are then consed onto this empty list to create the output list.
To extend on exnihilo's answer, once you have achieved familiarity with the type of solution that uses explicit recursion and pattern matching (opPairs ((a, b)::cs) = ...), you can begin to generalise the solution using list combinators:
val opPairs = map op+
I am stuck with a problem.
So the problem is.
I have a map like this {:first {"value1" "value2" "value3"...} :second {"value1" "value2" "value3"...}....}.
I have a function which
make a request to the server with parameters (first&value1) and return
some information (it must make request with each keys and their
values (first&value1, first&value2 ...second&value1...))
Next step is to generate new map like:
{:first
{:value1
{subvalue1, subvalue2 ..}
:value2
{subvalue2-1,subvalue2-2}}
:second
{:value3
{:subvalue3-1,:subvalue3-2}..}..}
Subvalues is the result of making a request with each key and each item of its value.
And i want to repeat the operation once again(with 3 parameters when I make a request to the server) to achieve 4 times nested map: {first {second {third {fourth}}}}.
Maybe somebody give me helpful advice how to do it.
This function is a bit long-winded but does what you need it to do:
(defn rec-update
[m f]
(let [g (fn g [m args]
(into {}
(for [[k v] m]
(if (instance? java.util.Map v)
[k (g v (conj args (name k)))]
[k (into {} (map #(let [args (into args [(name k) (name %)])]
[(keyword %) (f args)])
v))]))))]
(g m [])))
The f parameter should be a function that takes a collection of params, and returns a vector of results. Here is a sample that picks random numbers of random responses:
(defn make-request
[params]
(vec (repeatedly (+ 1 (rand-int 3)) #(rand-nth ["r1" "r2" "r3"]))))
Though the below example does not demonstrate, the params given to this function will indeed be the nested values up to that point.
To use:
(def m {:first ["val1" "val2" "val3"], :second ["val4" "val5"]})
(rec-update m make-request)
=>
{:first {:val1 ["r2" "r2" "r3"], :val2 ["r2" "r2"], :val3 ["r1" "r3"]},
:second {:val4 ["r3" "r3"], :val5 ["r2" "r1"]}}
Run it again on the result:
(rec-update *1 make-request)
=>
{:first {:val1 {:r2 ["r1" "r3" "r2"], :r3 ["r3" "r2"]},
:val2 {:r2 ["r1" "r1"]},
:val3 {:r1 ["r2"], :r3 ["r1" "r2" "r3"]}},
:second {:val4 {:r3 ["r3" "r2"]}, :val5 {:r2 ["r1"], :r1 ["r2" "r3"]}}}
As you can see, any duplicate values returned from the request will only be represented once in the result map.
Let's say that we have the following expression (band 'x (bor 'y 'z)), where band and bor boolean structs that have arg1 and arg2.
If I want to change the variables 'x and 'y to 'a and 'b by deep recursion on the expression, how can I do that?
There is a special form for functionally updating just some fields in a struct which is very nice to use where you have a lot of fields:
(struct person (name age occupation) #:transparent)
(define p (person "Per" 19 "Painter"))
(define (change-occupation p new-occupation)
(struct-copy person p [occupation new-occupation]))
(change-occupation p "Programmer") ; ==> (person "Per" 19 "Programmer")
Of course this is just a fancy way of writing:
(define (change-occupation p new-occupation)
(person (person-name p)
(person-age p)
new-occupation))
Now I don't know the names of your two structs but you may need to make a generic accessor unless one is subtype of the other:
(define (change-first obj new-value)
(if (band? obj)
(band new-value (band-second obj))
(bor new-value (bor-arg2 obj))))
Or you can just have similar case analysis in your procedure.
I have a list called attendance-events, consisting of struct type attendance-event. The struct is defined as
(define-struct attendance-event (date flag))
The "date" is the date of the event and "flag" is a 2 character value that represents the type of event.
In my database, I am selecting "select date, code from attendance_table", and I want those two columns to be added to the list of attendance-events for each row.
So, how can this be done?
This performs the query and returns a list of attendance-event structures:
(for/list ([(date code)
(in-query conn "select date, code from attendance_table")])
(make-attendance-event date code))
I find it much easier to work with database rows after they've been converted to hash tables. The following function converts the rows-result type returned by the query function into a list of immutable hashes:
(require (planet jphelps/loop)) ;; Use the loop macro from Common Lisp.
(define (rows-result->hash results)
(let ((header (rows-result-headers results)))
(loop for row in (rows-result-rows results)
collect (loop for ((_ . name) (_ . decltype)) in header
for column across row
with-collection-type hash/immutable
collect (cons name column)))))
Then you can wrap the query function like this:
(define (simple-query query-text conn . params)
(rows-result->hash (apply query (list* conn query-text params))))
Finally, to create your struct:
(loop for row in (simple-query "select date,code from attendance_table;")
collect (make-attendance-event (hash-ref row 'date) (hash-ref row 'code)))
I'm experimenting with the Pure language based on term rewriting.
I want to define "map fusion" using an equation, like this:
> map f (map g list) = map (f . succ . g) list;
(The succ is there to verify that the rule kicks in.)
However, it doesn't seem to work:
> map id (map id [2,3,4]);
[2,3,4]
The Pure manual says that
expressions are evaluated using the “leftmost-innermost” reduction strategy
So I suppose what's happening is that the innermost map id [2,3,4] expression is reduced first, so my rule never kicks in.
How to make map fusion work, then?
Here's a related experiment. The first rule doesn't kick in:
> a (b x) = "foo";
> b x = "bar";
> a (b 5);
a "bar"
I should have read the manual more closely. What I needed to do is to turn the pattern into a macro using the def keyword. This way it works:
> def map f (map g list) = map (f . succ . g) list;
> map id (map id [2,3,4]);
[3,4,5]