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.
I am dealing with an XML vocabulary that has "default values": i.e., if a node does not have a certain subnode, I'd like to find the nearest enclosing node that has that subnode, and use its string value as the value of the original node's subnode.
E.g., if I have a tree
Super_node
sub_node: XXX
...
context_node
/* does not have a child with name sub_node */
and no intervening nodes between Super_node and context_node have a child sub_node, I want an expression that evaluates to XXX.
I was thinking that the following query should work, but I always get a node list:
string(ancestor-or-self::*/sub_node[1]/text())
My thinking is that ancestor-or-self::* returns, in reverse document order, the list of context_node, parent_of_context_node, ..., Super_node. I apply the sub_node test to that, and get the list of sub_nodes in that list, again, hopefully, in reverse document order.
I then apply the predicate [1], which should return the first element of that list. However, this predicate seems to be not effective: in my implementation (which I think is based on libxml2), I still receive a list.
What does work, I found after poking around on Stack Exchange a bit, is
string((ancestor-or-self::*/sub_node)[last()]/text())
Why is the predicate [1] above not effective?
The expression
ancestor-or-self::*/sub_node[1]
means
ancestor-or-self::*/(child::sub_node[1])
which selects the first sub_node element child of every ancestor element.
I suspect you were thinking of
(ancestor-or-self::*/sub_node)[1]
which selects all the sub_node children of all the ancestor elements, sorts them into document order, and then returns the first node in this list.
Predicates like [1] bind more strongly than "/".
I am trying to go through a binary tree in an inorder traveling method
my target is to find the occurance of a specific key in the tree
for example,
i have the following tree:
t(t(t(nil,"d",t(nil,"g",nil)),"b",t(nil,"e",nil)),"a",t(t(nil,"f",t(nil,"h",nil)),"c",nil))
when i will use my inorder_finder i will get the following:
for "c" i will get 8
for "d" i will get 1
for "w" i will get -1
I have come up to the following code:
inorder_finder(nil,_,_,0).
inorder_place(t(_,X,_),X,Count,Place) :-
Place is Count+1.
inorder_place(t(L,_,R),Wanted,Count,Place) :-
inorder_place(L,Wanted,Count+1,Place),
Place<1,
inorder_place(R,Wanted,Count+1,Place),
Place<1,
Count = Count+1.
and i call the following predicate:
inorder_finder inorder_place(t(t(t(nil,"d",t(nil,"g",nil)),"b",t(nil,"e",nil)),"a",t(t(nil,"f",t(nil,"h",nil)),"c",nil)),"c",1,Place)
but it doesnt work at the moment. (just always returns false)
any ideas?
update: I have updated the code according to the comments i got - it still returns false and doesnt work as i would like it to
Most obvious errors have been mentioned in comments, what still remain are:
Place<1 : I don't get why?? Place may has value greater than 1.
inorder_place: never defined...
inorder_place(t(_,X,_),X,Count,Place):-Place is Count+1.: even if you find the letter you need first recursively enumerate the left branch of tree and then Place of wanted letter (see answer below)
I think the problem could be solved in two parts, one in-order-enumerate all nodes then simply traverse until you find the right node. Though I didn't followed this version (even it is more clear) since with a simple-mixed solution it is more efficient since you may not need to enumerate all nodes. For this attempt that you're trying to do I think you need two counters - first one the counter when calling inorder_find(..) e.g when entering, second counter will return where the counting stopped in order to continue from there in the right branch of tree.
inorder_finder inorder_place(...):still not valid syntax for calling the predicate- it should return error not false...
My implementation:
inorder_finder(nil,_,Count,Count,-1).
inorder_finder(t(L,X,_),X,Count,Count2,Place):-
inorder_finder(L,X,Count,Count3,_),
Place is Count3+1,Count2 is Place.
inorder_finder(t(L,X,R),Wanted,Count,Count2,Place):-
dif(X,Wanted),
inorder_finder(L,Wanted,Count,Count3,Place1),
Count4 is Count3+1,
inorder_finder(R,Wanted,Count4,Count2,Place2),
Place is max(Place1,Place2).
Examples:
?- inorder_finder(t(t(t(nil,"d",t(nil,"g",nil)),"b",t(nil,"e",nil)),"a",t(t(nil,"f",t(nil,"h",nil)),"c",nil)),"c",0,_,P).
P = 8 ;
false.
?- inorder_finder(t(t(t(nil,"d",t(nil,"g",nil)),"b",t(nil,"e",nil)),"a",t(t(nil,"f",t(nil,"h",nil)),"c",nil)),"W",0,_,P).
P = -1.
?- inorder_finder(t(t(t(nil,"d",t(nil,"g",nil)),"b",t(nil,"e",nil)),"a",t(t(nil,"f",t(nil,"h",nil)),"c",nil)),"d",0,_,P).
P = 1 ;
false.
Let's say I have a n-ary tree type
type tree = Node of (char*tree) list ref;;
and this correspond to the empty tree
let empty_tree ()= Node(ref[]);;
I'm trying to write a function that only looks if my tree is empty or not, such as
let checkIsEmpty t = match t with empty_tree-> print_string "tree is empty";;
But when I write checkIsEmpty empty_tree;; it just return a unit, it won't print "tree is empty"
I also tried that way
let checkisEmpty t = match t with z when z = empty_tree-> print_string "tree is empty";;
Sadly it still fails.
How can I look if my tree is empty? I'd like to keep the match with and the way tree is declared (Empty is not part of the type..) if possible.
Thanks!
You most likely need to flush the output to see it. You can write this:
print_string "tree is empty"; flush stdout
However, your first match doesn't work. Any identifier in a pattern introduces a new variable. So the variable empty_tree in your first implementation will always match whatever tree you pass to your function. (Or indeed it will match any value whatsoever.)
The second implementation should work a little better once you add flush stdout, and assuming there is a global value empty_tree that is an empty tree. But you should also add a case that matches when the tree is not empty; otherwise you'll get an exception for that case.
Furthermore your empty_tree is a function that returns an empty tree. It's not an empty tree itself (as your latest code is assuming).
(I would suggest you not modify your question too much after asking it. It makes it hard to write an answer that corresponds to what you asked.)
Ello, ive got the Prolog function member which tells us if an element exists in a list.
now i should create a function that returns a list without that element. i know more or less how it should look like, but somehow i have no idea how to do it.
ideas so far:
return the elements in the list before our element, and concat it with the rest of the list after our element.
use member() in a predicate that goes through the list recursively and builds it.
help.
(Seems like homework to me so I'll give you an outline containing some hints ;-)
Given [H|T]...
... if H is the element to remove, return T, (If you need to remove all such elements, remember to recurse on T as well.)
... if H is not the element to remove, return [H|NewTail] where NewTail is result of recursively removing the element from T.