Ocaml struct like we do in C - struct

I want to write a recursive struct, like we do in C, but in Ocaml.
I want we contains a boolean and a list of recursive copies of elements of the same type.
How can I do that in Ocaml?

OCaml type declarations are recursive by default. So there's nothing special to do to get something like you describe. If you literally want a list inside your struct, you can define something like this:
type mystruct = { b: bool; others: mystruct list }
If you want a "linked list" of structures of your given type, you could define something more like this:
type mystruct2 = { b: bool; rest : mystruct2 option }
One key here is that the rest element is an option type so that your list can end at some point.
There are many other ways to define this basic structure. A more idiomatic OCaml definition might be to use a variant type:
type mylist = Last | Node of bool * mylist
This last type isn't exactly equivalent because a value of your described type always contains at least one boolean, and this type has a value (Last) with no booleans. In practice this usually turns out to be what you want.
Update
Here are two top-level variables of each of these types. In each pair the first is as small as possible and the second is a little larger.
let v10 = { b = true; others = []}
let v11 = { b = false; others = [ {b = true; others = []} ] }
let v20 = { b = true; rest = None }
let v21 = { b = false; rest = Some { b = true; rest = None } }
let v30 = Last
let v31 = Node (true, Last)
If you have basic questions like this, it might be worthwhile to work through an OCaml tutorial, maybe one of those listed here: https://ocaml.org/learn/tutorials/

Related

Check serde_json Value for value with key sets of arbitrary depth or add if null Rust

With something like the vec below Id like to add arbitrary depth to a json object.
let set = vec![vec!["123","apple","orange","999"],vec!["1234","apple"],vec!["12345","apple","orange"]];
Once created the above would look something like:
{"123":{"apple":{"orange":"999"}}, "1234":"apple", "12345":{"apple":"orange"}}
Ive tried recursion, the issue Im running into is that Im having trouble reasoning through it. The wall Ive hit is how do I refer up the chain of values?
Is there a method Im missing here? Surely Im not the only person whos wanted to do this...
I would prefer if at all possible not writing something cumbersome that takes the length of a key set vec and matches creating the nesting ex.:
match keys.len() {
2 => json_obj[keys[0]] = json!(keys[1]),
3 => json_obj[keys[0]][keys[1]] = json!(keys[2]),
4 => json_obj[keys[0]][keys[1]][keys[2]] = json!(keys[3]),
...
_=> ()
}
Any ideas?
You can do this with iteration -- each loop you walk deeper into the structure, and further into the iterator, but the trick is that each step you need to know if there are more elements beyond the final one because the final element needs to be a string instead of an object. We'll do this using a match construct that matches on the next two items in the sequence at once.
We can further generify the function to take "anything that can be turned into an iterator that produces items from which we can obtain a &str". This will accept both an iterator of String or an iterator of &str, for example, or even directly a Vec of either.
use std::borrow::Borrow;
use serde_json::Value;
fn set_path(
mut obj: &mut Value,
path: impl IntoIterator<Item=impl Borrow<str>>
) {
let mut path = path.into_iter();
// Start with nothing in "a" and the first item in "b".
let mut a;
let mut b = path.next();
loop {
// Shift "b" down into "a" and put the next item into "b".
a = b;
b = path.next();
// Move "a" but borrow "b" because we will use it on the next iteration.
match (a, &b) {
(Some(key), Some(_)) => {
// This level is an object, rebind deeper.
obj = &mut obj[key.borrow()];
}
(Some(s), None) => {
// This is the final string in the sequence.
*obj = Value::String(s.borrow().to_owned());
break;
}
// We were given an empty iterator.
(None, _) => { break; }
}
}
}
(Playground)

How to write multiple condition in if let statement?

How to modify if let statement so it also handles another condition like Some(7) == b?
let a = Some(6);
let b = Some(7);
if let Some(6) = a /* && Some(7) = b */{
// do something
}
You can use a simple tuple:
if let (Some(6), Some(7)) = (a, b) {
// do something
}
The if let expression only admits one match arm pattern against one expression. However, they can be merged together into a single equivalent pattern match condition. In this case, the two Option values can be combined into a pair and matched accordingly.
if let (Some(6), Some(7)) = (a, b) {
// do something
}
Playground
See also:
Simplest way to match multiple fields of a struct against `None`

Is there a way to pass named arguments to format macros without repeating the variable names?

With new versions of Rust, you can simplify structure initialization like this:
Foo {
a: a,
b: b,
}
to this
Foo { a, b }
Is it possible to do something similar for format!/println!-like macros?
For now I need to write it like this:
let a = "a";
let b = "b";
write!(file, "{a} is {b}", a = a, b = b).unwrap();
Is it possible to write my own macros with an API like this:
let a = "a";
let b = "b";
my_write!(file, "{a} is {b}", a, b).unwrap();
RFC 2795 has been accepted and implemented. Starting in Rust 1.58, you will be able to go beyond your desired syntax:
write!(file, "{a} is {b}").unwrap();
Before then, you can write your own wrapper around println! and friends:
macro_rules! myprintln {
($fmt:expr, $($name:ident),*) => { println!($fmt, $($name = $name),*) }
}
fn main() {
let a = "alpha";
let b = "beta";
myprintln!("{a} is {b}", a, b);
}
This will likely always be limited compared to the full formatter macro, but it may be sufficient for your case.
As of 1.5 this is the closest you can get natively.
my_write!(file, "{} is {}", a, b).unwrap();
Additionally as Shepmaster pointed out my answer will eventually become obsolete (I'll try to remember to remove it when that happens). If you want to keep an eye on the (to be implemented) syntax they propose you can check this github ticket they linked

Assign a single value to multiple variables in one line in Rust?

A common way to assign multiple variables is often expressed in programming languages such as C or Python as:
a = b = c = value;
Is there an equivalent to this in Rust, or do you need to write it out?
a = value;
b = value;
c = value;
Apologies if this is obvious, but all my searches lead to Q&A regarding tuple assignment.
No, there is no equivalent. Yes, you have to write multiple assignments, or write a macro which itself does multiple assignments.
You cannot chain the result of assignments together. However, you can assign multiple variables with a single statement.
In a let statement, you can bind multiple names by using an irrefutable pattern on the left side of the assignment:
let (a, b) = (1, 2);
(Since Rust 1.59, you can also have multiple values in the left side of any assignment, not just let statements.)
In order to assign the same value to multiple variables without repeating the value, you can use a slice pattern as the left-hand side of the assignment, and an array expression on the right side to repeat the value, if it implements Copy:
let value = 42;
let [a, b, c] = [value; 3]; // or: let [mut a, mut b, mut c] = ...
println!("{} {} {}", a, b, c); // prints: 42 42 42
(Playground)
Using const generics:
fn main() {
let [a, b, c] = fill_new_slice(1);
dbg!(a, b, c);
}
fn fill_new_slice<T: Copy, const N: usize>(value: T) -> [T; N] {
[value; N]
}
$ cargo run --quiet
[src/main.rs:3] a = 1
[src/main.rs:3] b = 1
[src/main.rs:3] c = 1
Actually, you can totally do this!
let a # b # c = value;
This uses the # syntax in patterns, which is used to bind a value to a variable, but keep pattern matching. So this binds value to a (by copy), and then continues to match the pattern b # c, which binds value to b, and so on.
But please don't. This is confusing and of little to no benefit over writing multiple statements.
In Rust, the expression a = b = c = value; is the same to a = (b = (c = value));
And the (x = ...) returns (). Then, the first expression is an equivalent of the following:
c = value;
b = ();
a = ();
Note that the expression has a semicolon in the end, but if the expression were in the last line as a function's return like this a = b = c = value, the equivalente would be the following:
c = value;
b = ();
a = () // without the semicolon

How to clear values of a instance of a type struct dynamically

Is it possible with Go to make a method that dynamically clears the values of a instance of a struct?
type A struct {
Name string
Level int
}
type B struct {
Skill string
}
func main() {
a := A{"Momo", 1}
b := B{"Starfall"}
// outputs
// {"Momo", 1}
// {"Starfall"}
clear(a)
clear(b)
// outputs
// { , 0}
// { }
}
func clear(v interface{}) {
// some code
}
You can't modify the original values without passing a pointer to them.
It's much easier and more clear to simply assign a new zero value in your code. If your types are more complex, you can replace the values with a constructor, or provide Reset() methods for your types with a pointer receiver.
If you really want to see how to do it via reflection your clear function could look like: http://play.golang.org/p/g0zIzQA06b
func clear(v interface{}) {
p := reflect.ValueOf(v).Elem()
p.Set(reflect.Zero(p.Type()))
}
(This will panic if you pass in a non-pointer value)
Even though this question was first asked 3 years and 9 months ago it IMO still does not have a good answer so let me propose one.
There is no need for reflection, or to create a new instance each time you want to clear your variable. Instead create one pristine new instance that you leave in its initial zeroed state which you can then copy over your object's memory when you want to Reset() it. (Hat tip to #DaveC for pointing out that a Reset() method is more idiomatic.)
You simply copy from your zeroed value to the location at which your object points to using pointers. The following reads "Copy the value of the memory that zeroA references to the memory location that a references.":
*a = *zeroA
Here is my full example which you can also try in the Go Playground. (Note that since your receiver for Reset() is a pointer to type A then calling the Reset() method allows you to update the value of a where the update survives past the end of the method call):
package main
import (
"fmt"
)
type A struct {
Name string
Level int
}
var zeroA = &A{}
func (a *A) Reset() {
*a = *zeroA
}
func main() {
a1 := A{"Momo", 1}
a2 := &a1
a3 := a1
fmt.Println(a1)
fmt.Println(a2)
fmt.Println(a3)
a1.Reset()
fmt.Println(a1)
fmt.Println(a2)
fmt.Println(a3)
}
And here is your output (Note that I prove that your variable is zeroed out and a pointer to that variable is also zeroed, but if you made a *copy* of the original it is not zeroed):
{Momo 1}
&{Momo 1}
{Momo 1}
{ 0}
&{ 0}
{Momo 1}
You can also use this technique to copy over the values of a struct that contains default values. However be aware that this is a shallow copy, not a deep copy. If your struct contains any properties that are pointers this approach will copy the pointer values over too and will not allocate memory to point to new copies of the values pointed to. So you will need to do extra work in Reset() if you want to reset your struct to new defaults, including copies of any sub-structs that are declared with pointers.
I hope this helps others so they do not have to learn this the hard way like it took me.
You can just set it to an empty struct like so:
var obj myStruct
obj.field1 = "apple"
obj.field2 = 12
// Reset struct.
obj = myStruct{}
Playground link: https://play.golang.org/p/Rf1BqfFe3IQ
It's possible to reassign the value with an empty object of the struct which will reset the values.
a := A{"Momo", 1}
b := B{"Starfall"}
fmt.Println(a)
fmt.Println(b)
// outputs
// {"Momo", 1}
// {"Starfall"}
a = A{}
b = B{}
// outputs
// { , 0}
// { }
https://play.golang.org/p/CJ6cx2TFytY

Resources