Clojure collection atom with selected item - data-structures

What is the best way in Clojure (actually ClojureScript) to accomplish the following:
A mutable collection of elements xs, each of type T (T is a map, if we want to be specific)
A "selected element" among them, x, which alternates between various xs or a "none selected" state. The number of selected items is either 1 or zero.
xs and x will have event listeners listening to them: some listen for any change in xs; some listen to any change in x. (That is, they listen for both an update in the state of the selected item, as well as a switching of which item is selected.) (I'm actually using the Reagent wrapper for React, so this affects when components will update.)
Methods to edit x (don't need to edit non-selected xs, though need to be able to add new xs)
Given an element in xs, a method to select it. (Including the case of select "none")
Possibilities I've thought of so far:
Make xs an atom which is a vector of Ts, and make sure every T element knows its own index. Replace x with x_idx which stores the index of the selected item (or nil). Selecting an element just means getting its index and changing x_idx to that index, both of which are constant-time ops. Downsides to this are that it makes the structure a little less elegant and simple: I'm always passing around the index of the selected item, and every operation I want to do has to work with the index instead of the item itself, as it would like to. Since my T objects are small, it would be more pleasing to just have a "selected object" variable which is of type T.
Make xs an atom vector and x an atom which stores a T. Now x is a T, which is nice, but when I want to update info about x, I have to make two calls to reset! or swap!: one for x and one for the element in xs which x represents. Inelegant for obvious reasons. And I have to do these in quick succession or else there will be an inconsistency in the data: in between the two calls, the event listeners listening to xs will see the selected item in one state, and the ones listening to x will see it in another state.
Give T elements a field to tell if they're selected or not, and get rid of x. This would be right if multiple items could be selected at once, but since only one item can be selected, it just makes me do a linear search every time I want the selected item, which sucks.
The point of this question is not to solve some particular issue (any of the possibilities above work fine for the scope of the small project I'm working on), but to learn about Clojure data structures. This seems like a common enough situation that there would be some structure around it. Responses along the lines of "you should be trying to answer a different question entirely..." are welcome.

You (I) want to look into cursors and reactions, two of the more advanced features of Reagent atoms. They can be used to have a collection and a selected element inside it which is automatically updated. See here for example.
Suppose you have a r/atom holding vector of objects and you want to have a selected object which can change, and which is directly editable. One way to achieve this is to keep an atom storing the index of the selected item and then
(defn my-get-set
([_k] (#vector-of-items #idx-of-selected-item))
([_k v] (reagent.core/rswap! my-state-vector assoc #idx-of-selected-item v)))
(def selected-item (reagent.core/cursor my-get-set []))
Edit: Changed reagent.core/cursor my-get-set nil to reagent.core/cursor my-get-set []. The former leads to problems.

Related

How does Cons save data (Rust Linked List)

I have been learning Rust and decided doing some basic type would help to learn the language at a deeper level.
The "Rust by Example" page for linked lists states
Ln 4: // Cons: Tuple struct that wraps an element and a pointer to the next node
Which I think means that it is recursively creating the list by always making an empty node to populate with Cons.
enum linkedList
{
Head(Head), // Front Pointer and list metrics
Cons(Arc<linkedList>, isize), //(Data, Next Value) Cons is apparently a LISP construct
Tail(isize), // Rear Pointer
Nil //Used to drop the stream
}
My real question is what is the underlying mechanism that allows data to be stored in the Arc<linkedList> node? I thought it would take a generic (<T>) to store the data on the list but apparently this is incorrect.
p.s I am under the impression ARC and BOX smart pointers are interchangeable but used for different purposes. I was trying to make a thread safe version of a single ended rollover safe linked list, sort of like a circular queue.
Your implementation slightly deviates from the standard definition of Cons lists. The straight-forward definition (similar to how you would do it in Lisp) is
type Data = isize;
enum List {
Nil,
Cons(Box<List>, Data),
}
As you can see, the Cons variant is made up of the nested list and this nodes data element. In your case, each node has an isize.
If you have an Arc<List> or Box<List>, this nested List object could be the Cons variant too and carry another isize. Arc and Box don't care about what they are pointing to.
There are some things that are not quite idiomatic. Having both the Tail and Nil variant doesn't make much sense, because now you have two ways to signal the end of the list. Similarly, having the Head be a variant of the list is strange, because the head of the list is only at the beginning, your implementation allows for a Head variant in the middle of the list though.
It is preferable to not have an extra Nil node to signal the end of the list. Instead, the last node knows that it is the last (like your Tail variant) so that you don't have an extra allocation for the empty node. This is what I would perceive as an idiomatic definition of a singly linked list in Rust:
struct List {
// ...
// extra info for list head
// ...
first_node: Option<Box<ListNode>>,
}
struct ListNode {
value: Data,
next: Option<Box<ListNode>>,
}
To make this generic, we simply have to remove our type alias Data from earlier and make it a generic parameter instead:
struct ListNode<T> {
value: T,
next: Option<Box<ListNode<T>>>,
}
About Box and Arc: Box is an owned pointer to a value on the heap, that means only this one box owns the memory it points to. Arc is a thread safe version of Rc, which is a reference-counted heap value. Multiple Rc-pointers to this memory can exist and read it, the number of these is counted. Thus, the ownership may be shared.
You should pick which to use, based on whether or not you want to create more reference-counted pointers to the nodes (note that you probably want either Rc<RefCell<Node>> or Arc<Mutex<Node>> to also mutate the list after creating it). If you only ever have the head of the list and want to iterate over it, pick Box instead.

How do I prevent to operate over an empty matrix or a matrix with empty columns or row?

In the problem that I want to solve a well defined matrix has no empty rows or columns.
For example the matrix [[],[]] is not valid.
When I call the function first_column, how do I prevent to execute it if the matrix that I send as an argument is not valid as defined before?
first_column([],[],[]).
first_column([[H|T]|Tail],[H|Col],[T|Rows]):- first_column(Tail,Col,Rows).
Technically, what you're asking can be done by testing for an end-condition of a list with one element, rather than an empty list, based on the specs you gave.
first_column([[H|T]],[H],[T]).
first_column([[H|T]|Tail],[H|Col],[T|Rows]):- first_column(Tail,Col,Rows).
However, beyond your specs, I suspect that you'll also need to "transfer" your final Col,Rows to end variables, something like:
first_column([[H|T]],C,R,[H|C],[T|R]).
first_column([[H|T]|Tail],[H|C],[T|R],Col,Rows):-
first_column(Tail,C,R,Col,Rows).
The modified predicate would be called with initial conditions, like
first_column(List,[],[],Col,Rows).

count elements of list,using pattern

I have some questions, can anybody show how to solve them?
1)How to count elements of list specific to level, independently of sort Exrp?
Just like the number of elements subset.
for example {{1,2,3,4,5},{5,6,7,8,9}} , at level 1 it should yield 10.
I ve been trying to done this by Count[] , but it dont work so even if i choose pattern _ (i can count them separately specifying pattern, but i cant use multi-pattern (see below) , if i specifying _ then it count some lists above target level).
2)How i can assert something like NumberQ or EvenQ to content of list using list as function argument (ie list must contain specific mathematica expr. ) and how to create multi pattern like( f[x_List?NumberQ or EvenQ,y_List?NumberQ or EvenQ]
Thanks.
The first question has already been answered in comments.
For the second version, -Q functions are not automatically threaded
and combined (as there are several ways to combine tests on a list).
You have to do explicitely.
Here is one way to do it:
f[x_List,y_List]:= Join[x,y] /; (And##Map[EvenQ,x] && And##Map[EvenQ,y])
This syntax defines how to compute f if the conditions on the right are satisfied. f will remain unevaluated if at least one test does not yields true.
If the kind of test you like comes often, you can define auxiliary functions:
test if a list contains only even numbers
evenlistQ[x_List]:= And##Map[EvenQ, x]
test if a list contains only items verifying both test_A and test_B
AandBlistQ[x_List]:= And##Map[testA[#]&&testB[#]&, x]
test if a list contains only items verifying at least one of test_A or test_B
AorBlistQ[x_List]:= And##Map[testA[#]||testB[#]&, x]
test if a list is either completely verifying test_A or completely verifying test_B
AlistOrBlistQ[x_List]:= (And##Map[testA,x] || And##Map[testB,x])
Then you could write
f[ x_List?evenlistQ, y_List?evenlistQ] := Join[x,y]
that would evaluate only if both arguments are lists of verifying your requirements and left unevaluated if not.
This last form is equivalent to
f[ x_List, y_List] := Join[x,y] /; (evenlistQ[x]&& evenlistQ[y])
which allows more flexibility for constraints verification.

Difference between multiple values and plain tuples in Racket?

What is the difference between values and list or cons in Racket or Scheme? When is it better to use one over the other? For example, what would be the disadvantage if quotient/remainder returns (cons _ _) rather than (values _ _)?
Back in 2002 George Caswell asked that question in comp.lang.scheme.
The ensuing thread is long, but has many insights. The discussion
reveals that opinions are divided.
https://groups.google.com/d/msg/comp.lang.scheme/ruhDvI9utVc/786ztruIUNYJ
My answer back then:
> What are the motivations behind Scheme's multiple return values feature?
> Is it meant to reflect the difference in intent, or is there a
> runtime-practical reason?
I imagine the reason being this.
Let's say that need f is called by g. g needs several values from f.
Without multiple value return, f packs the values in a list (or vector),
which is passed to g. g then immediately unpacks the list.
With multple values, the values are just pushed on the stack. Thus no
packing and unpacking is done.
Whether this should be called an optimization hack or not, is up to you.
--
Jens Axel Søgaard
We don't need no side-effecting We don't need no allocation
We don't need no flow control We don't need no special-nodes
No global variables for execution No dark bit-flipping for debugging
Hey! did you leave the args alone? Hey! did you leave those bits alone?
(Chorus) -- "Another Glitch in the Call", a la Pink Floyd
They are semantically the same in Scheme and Racket. In both you need to know how the return looks like to use it.
values is connected to call-with-values and special forms like let-values are just syntax sugar with this procedure call. The user needs to know the form of the result to use call-with-values to make use of the result. A return is often done on a stack and a call is also on a stack. The only reason to favor values in Scheme would be that there are no overhead between the producer return and the consumer call.
With cons (or list) the user needs to know how the data structure of the return looks like. As with values you can use apply instead of call-with-values to do the same thing. As a replacement for let-values (and more) it's easy to make a destructuring-bind macro.
In Common Lisp it's quite different. You can use values always if you have more information to give and the user can still use it as a normal procedure if she only wants to use the first value. Thus for CL you wouldn't need to supply quotient as a variant since quotient/remainder would work just as well. Only when you use special forms or procedures that take multiple values will the fact that the procedure does return more values work the same way as with Scheme. This makes values a better choice in CL than Scheme since you get away with writing one instead of more procedures.
In CL you can access a hash like this:
(gethash 'key *hash* 't)
; ==> T; NIL
If you don't use the second value returned you don't know if T was the default value or the actual value found. Here you see the second value indicating the key was not found in the hash. Often you don't use that value if you know there are only numbers the default value would already be an indication that the key was not found. In Racket:
(hash-ref hash 'key #t)
; ==> #t
In racket failure-result can be a thunk so you get by, but I bet it would return multiple values instead if values did work like in CL. I assume there is more housekeeping with the CL version and Scheme, being a minimalistic language, perhaps didn't want to give the implementors the extra work.
Edit: Missed Alexis' comment on the same topic before posting this
One oft-overlooked practical advantage of using multiple return values over lists is that Racket's compose "just works" with functions that return multiple values:
(define (hello-goodbye name)
(values (format "Hello ~a! " name)
(format "Goodbye ~a." name)))
(define short-conversation (compose string-append hello-goodbye))
> (short-conversation "John")
"Hello John! Goodbye John."
The function produced by compose will pass the two values returned by hello-goodbye as two arguments to string-append. If you're writing code in a functional style with lots of compositions, this is very handy, and it's much more natural than explicitly passing values around yourself with call-with-values and the like.
It's also related to your programming style. If you use values, then it usually means you want to explicitly return n values. Using cons, list or vector usually means you want to return one value which contains something.
There are always pros/cons. For values: It may use less memory on some implemenentations. The caller need to use let-values or other multiple values specific syntax. (I wish I could use just let like CL.)
For cons or other types: You can use let or lambda to receive the returning value. You need to explicitly deconstruct it to get the value you want using car or other procedures.
Which to use and when? Again depending on your programming style and case by case but if the returning value can't be represented in one object (e.g. quotient and remainder), then it might be better to use values to make the procedure's meaning clearer. If the returning value is one object (e.g. name and age for a person), then it might be better to use cons or other constructor (e.g. record).

A function in Scheme to replace all occurrences of an element in a list with another element

I am able to delete the element from a list, but I have no idea how to write a function in Scheme to replace all occurrences of an element in a list with another element.
Any help will be appreciated.
A simple version might be designed like this:
(define (replace old-element new-element list)
; if the list is null, just return null
; else if the car of the list is equal to old-element
; run replace on the rest of the list, and cons new-element onto it
; else
; run replace on the rest of the list, and cons the car onto it)
(I left the details up to you, since you gotta learn by doing.)
Remember, in Scheme the most natural way to do things will usually be to assemble a new list piece-by-piece from your old list, not to try to make little changes one at a time to your old list.
Note that you could also use map to do this much more concisely.

Resources