Common Lisp: Appending a nested plist efficiently - nested

I am using a nested plist in order to create a structure of objects (CLOS type), passing on the nested ones to its parts. I want to append the nested plist in an iterative way, but therefore I want to do it efficiently in terms of time and memory.
The below example shows the delta due to one iteration:
'(:airframer "Boeing" :type "777" :wing-plist ((:side :left :winglet? nil)
(:side :right :winglet? nil)))
into
'(:airframer "Boeing" :type "777" :wing-plist ((:type :main-wing :side :left)
(:type :main-wing :side :right)
(:type :stabilizer :size :left)))
I already read that the use of vectors instead of lists might help, as you access elements without too much penalty: Replace an item in a list in Common Lisp?. However, I would really like to bypass the use of vectors.
Furthermore, I think the use a destructive function would save memory and hopefully calculation time.
This is how I solved it now at the moment, but I have the feeling that it is not elegant and efficient. The function fill is used for destructiveness.
(defun append-nested-plist (plist key sub-plist)
(let* ((key-pos (position key plist)))
(fill plist (append (getf plist key) (list sub-plist))
:start (+ key-pos 1) :end (+ key-pos 2))))
I am looking forward to your answers.

How about this?
(defun append-nested-plist (plist key sub-plist)
(push-to-end sub-plist (getf plist key))
plist)
Push-to-end is a commonly-defined macro that's not part of the common lisp standard:
(defmacro push-to-end (item place)
`(setf ,place (nconc ,place (list ,item))))

Related

Recursively reading a file in Racket

I am struggling to understand how to read a file line by line with racket, while passing each line to a recursive function.
According to the manual, the idiomatic way of doing this is something like the following example:
(with-input-from-file "manylines.txt"
(lambda ()
(for ([l (in-lines)])
(op l))))
What if my function op is a recursive function that needs to do some complicated operations depending on the line just read from file and also on the history of the recursion?
For example, I could have a function like this:
(define (op l s)
;; l is a string, s is a list
(cond ((predicate? l)
(op (next-line-from-file) (cons (function-yes l) s)))
(else
(op (next-line-from-file) (append (function-no l) s)))))
I am not sure how to use this function within the framework described by the manual.
Here next-line-from-file is a construct I made up to make it clear that I would like to keep reading the file.
I think I could do what I want by introducing side effects, for example:
(with-input-from-file "manylines.txt"
(lambda ()
(let ((s '()))
(for ([l (in-lines)])
(if (predicate? l)
(let ((prefix (function-yes l)))
(set-cdr! s s)
(set-car! s prefix))
(let ((prefix (function-no l)))
(set-cdr! prefix s)
(set-car! s prefix)))))))
I actually did not try to run this code, so I'm not sure it would work.
Anyway I would bet that this common task can be solved without introducing side effects, but how?
Two approaches that Racket supports rather well are to turn the port into something which is essentially a generator of lines, or into a stream. You can then pass these things around as arguments to whatever function you are using in order to successively read lines from the file.
The underlying thing in both of these is that ports are sequences, (in-lines p) returns another sequence which consists of the lines from p, and then you can turn these into generators or streams.
Here's a function which will cat a file (just read its lines in other words) using a generator:
(define (cat/generator f)
(call-with-input-file f
(λ (p)
(let-values ([(more? next) (sequence-generate (in-lines p))])
(let loop ([carry-on? (more?)])
(when carry-on?
(displayln (next))
(loop (more?))))))))
Here call-with-input-file deals with opening the file and calling its second argument with a suitable port. in-lines makes a sequence of lines from the port, and sequence-generate then takes any sequence and returns two thunks: one tells you if the sequence is exhausted, and one returns the next thing in it if it isn't. The remainder of the function just uses these functions to print the lines of the file.
Here's an equivalent function which does it using a stream:
(define (cat/stream f)
(call-with-input-file f
(λ (p)
(let loop ([s (sequence->stream (in-lines p))])
(unless (stream-empty? s)
(displayln (stream-first s))
(loop (stream-rest s)))))))
Here the trick is that sequence->stream returns a stream corresponding to a sequence, and then stream-empty? will tell you if you're at the end of the stream, and if it's not empty, then stream-first returns the first element (conceptually the car) while stream-rest returns a stream of all the other elements.
The second one of these is nicer I think.
One nice thing is that lists are streams so you can write functions which use the stream-* functions, test them on lists, and then use them on any other kind of stream, which means any other kind of sequence, and the functions will never know.
I recently implement something similar, except in my case the predicate depended on the following line, not the preceding one. In any case, I found it simplest to discard in-lines and use read-line recursively. Since the predicate depended on unread input, I used peek-string to look ahead in the input stream.
If you really want to use in-lines, you might like to experiment with sequence-fold:
(sequence-fold your-procedure '() (in-lines))
Notice this uses an accumulator, which you could use to check the previous results from your procedure. However, if you're building a list, you generally want to build it backwards using cons, so the most recent element is at the head of the list and can be accessed in constant time. Once you're done, reverse the list.

Contingent Multi-thread, but Not Single-thread, Bug (Common Lisp)

I've narrowed a problem down to one particular function call to one of my library routines that looks like (pop-hstack current-hstack), which pops an element from a stack structure. It is causing data corruption (an inconsistency, see below) in the stack structure, but only when multiple threads are running. I've tried wrapping the call in a lock like so (bt:with-lock-held (*lock*) (pop-hstack current-hstack), but current-hstack is still becoming inconsistent somewhere during execution when there are two or more threads active. The arguments to pop-hstack (eg, current-hstack) in each thread are dynamically bound special variables, and so are not shared between threads. It's confusing whether the inconsistency is being introduced by multi-threading (no inconsistency running single-thread), or perhaps by a contingent programming bug in the structure definition or pop-hstack function.
(defstruct hstack
"An hstack (hash stack) is an expanded stack representation containing an
adjustable one-dimensional array of elements, plus a hash table for quickly
determining if an element is in the stack. Keyfn is applied to elements to
access the hash table. New elements are pushed at the fill-pointer, and
popped at the fill-pointer minus 1."
(vector (make-array 0 :adjustable t :fill-pointer t) :type (array * (*)))
(table (make-hash-table) :type hash-table) ;can take a custom hash table
(keyfn #'identity :type function)) ;fn to get hash table key for an element
(defun pop-hstack (hstk)
"Pops an element from hstack's vector. Also removes the element's index from
the element's hash table entry--and the entry itself if it's the last index."
(let* ((vec (hstack-vector hstk))
(fptr-1 (1- (fill-pointer vec)))
(tbl (hstack-table hstk))
(key (funcall (hstack-keyfn hstk) (aref vec fptr-1))))
(when (null (setf (gethash key tbl) (delete fptr-1 (gethash key tbl))))
(remhash key tbl))
(vector-pop vec)))
Normally, hstack's stack vector and hash table are in sync, containing the same number of entries: (length (hstack-vector x)) = (hash-table-count (hstack-table x)). Only when there are duplicate elements in hstack, will the number of entries differ. (Because then a single hash table entry will contain multiple vector indices for duplicate elements appearing in the vector.) However, the inconsistency between the number of entries in the vector and the hash table still shows up when there are no duplicate elements. Typically, there are one or two extra elements in the hash table, indicating that these extra elements were not properly removed during a pop-hstack operation. The stack vector always seems to have the correct elements.
EDIT(5/2/19): Corrected a coding error in pop-hstack: Replace (delete fptr-1 (gethash key tbl)) with (setf (gethash key tbl) (delete fptr-1 (gethash key tbl))).
The form (delete fptr-1 (gethash key tbl)) might be the cause, it modifies the list structure so that concurrent access might see a corrupt list.
What's the definition of the push operation?
Does corruption also occur if all push and all pop operations are wrapped in with-lock-held (using the same lock)?

how to retrieve a key in a map whose value contains a particular substring in clojure?

i need to retrieve the key whose value contains a string "TRY"
:CAB "NAB/TRY/FIGHT.jar"
so in this case the output should be :CAB .
I am new to Clojure, I tried a few things like .contains etc but I could not form the exact function for the above problem.its easier in few other languages like python but I don't know how to do it in Clojure.
Is there a way to retrieve the name of the key ?
for can also filter with :when. E.g.
(for [[k v] {:FOO "TRY" :BAR "BAZ"}
:when (.contains v "TRY")]
k)
First, using .contains is not recommended - first, you are using the internals of the underlying language (Java or JavaScript) without need, and second, it forces Clojure to do a reflection as it cannot be sure that the argument is a string.
It's better to use clojure.string/includes? instead.
Several working solutions have been already proposed here for extracting a key depending on the value, here is one more, that uses the keep function:
(require '[clojure.string :as cs])
(keep (fn [[k v]] (when (cs/includes? v "TRY") k))
{:CAB "NAB/TRY/FIGHT.jar" :BLAH "NOWAY.jar"}) ; => (:CAB)
The easiest way is to use the contains method from java.lang.String. I'd use that to map valid keys, and then filter to remove all nil values:
(filter some?
(map (fn [[k v]] (when (.contains v "TRY") k))
{:CAB "NAB/TRY/FIGHT.jar" :BLAH "NOWAY.jar"}))
=> (:CAB)
If you think there is at most one such matching k/v pair in the map, then you can just call first on that to get the relevant key.
You can also use a regular expression instead of .contains, e.g.
(fn [[k v]] (when (re-find #"TRY" v) k))
You can use some on your collection, some will operate in every value in your map a given function until the function returns a non nil value.
We're gonna use the function
(fn [[key value]] (when (.contains values "TRY") key))
when returns nil unless the condition is matched so it will work perfectly for our use case. We're using destructuring in the arguments of the function to get the key and value. When used by some, your collection will indeed be converted to a coll which will look like
'((:BAR "NAB/TRY/FIGHT.jar"))
If your map is named coll, the following code will do the trick
(some
(fn [[key value]] (when (.contains value "TRY") key))
coll)

What is the best way to append to an array in each iteration of a loop on a map using clojure?

I have created a structure which builds a URL query from a map but it is not thread-safe since it's relying on a defined variable which probably isn't needed so what is the best way to do this?
(def charset "UTF-8")
(defn make-query
[params]
(do
(def tmpa [])
(doseq [keyval params]
(def tmpa
(into tmpa
[(str
(java.net.URLEncoder/encode (name (first keyval)) charset)
"="
(java.net.URLEncoder/encode (apply (first keyval) [params]) charset)
)]
)
)
)
(clojure.string/join "&" tmpa)
)
)
The use of nested defs is not really the way to go when you need to work with an intermediate value in a function, that's what the let form is for. Also note that def creates a top level var, so even after the make-query function returns, you will still have a tmpa var lying around in the namespace where you declared the function.
The function you posted has an imperative style since it's using doseq (which is by definition to be used for side-effects) and changing the value of the tmpa var in every iteration of the loop.
A functional approach would be reduceing the key-value pairs and build the result by concatenating the key and value to the query string in each call to the reducing function. The following is an example of how this can be achieved:
(def charset "UTF-8")
(defn make-query
[params]
(reduce (fn [query [k v]]
(str query
(java.net.URLEncoder/encode (name k) charset)
"="
(java.net.URLEncoder/encode (str v) charset)
"&"))
""
params))
(make-query {:name "clojure" :year 2014})
;= "name=clojure&year=2014&"
It takes some time to get used to thinking this way, when one comes from an imperative and OOP background, but with practice it gets a lot easier.
Hope it helps.

Update the whole structure

Suppose I have some function which returns a struct:
(struct layer (points lines areas))
(define (build-new-layer height)
...
(layer list-a list-b list-c))
I want to keep track of the last returned result something like:
(define top-side (build-new-layer 0)) ; store the first result
...
(set! top-side (build-new-layer 0.5)) ; throw away the first result and store the new one
However, for that particular code I get the error:
set!: assignment disallowed;
cannot modify a constant
constant: top-side
Please, tell me what would be the right way to do what I want
What language are you using? it seems it's a matter of configuration, because in principle what you're doing should work. Go to the "choose language" window (Ctrl+L in Windows), click on "show details" and see if one of the options of the language currently in use disallows redefinition of variables. Alternatively, try using a different language.
Depending on where exactly you're going to use the stored result (I can't tell from the code in the question), you could pass it around as function parameters, in such a way that using a global variable is no longer necessary. This might be a better idea, relying on global state and mutation (the set! operation) is discouraged in Scheme.
If you always want to keep around the last layer, then you might prefer setting the last-layer every time one is built. Like this.
(define last-layer #f)
(define build-new-layer
(let ((save-layer #f))
(lambda (height)
(let ((new-layer (layer list-a ...)))
(set! last-layer save-layer)
(set! save-layer new-layer)
new-layer))))
Note: if the real problem is the 'constant-ness' of last-layer then build yourself a little abstraction as:
(define-values (last-layer-get last-layer-set!)
(begin
(define last-layer-access
(let ((last-layer #f))
(lambda (type . layer)
(case type
((get) last-layer)
((set) (set! last-layer (car layer)))))))
(values (lambda () (last-layer-access 'get))
(lambda (layer) (last-layer-access 'set layer))))

Resources