How do I create a mutable reference to an object in another object? - nim-lang

When I try to create two objects, where the second object has a reference to the first, I get Error: invalid type: 'var Foo' in this context: 'Bar' for var:
type
Foo = object
x: int
type
Bar = object
foo: var Foo
var f = Foo(x: 10)
var b = Bar(foo: f)
https://play.nim-lang.org/#ix=3RG3
How do I get this to work?

I think you need to create a ref Object for Foo. You can see plenty of examples for this in the sources (e.g. JsonNode and JsonNodeObj here), and is documented here and here.
type
Foo = object of RootObj
x: int
FooRef = ref Foo
Bar = object
foo: FooRef
var f = FooRef(x: 10)
var b = Bar(foo: f)
f.x = 30
doAssert b.foo.x == 30
The suffix of the object is not mandatory, but the convention is to use Ref for the ref objects and Obj for value objects (naming conventions). E.g. you can write the above as:
type
Foo = ref FooObj
FooObj = object of RootObj
x: int
Bar = object
foo: Foo
var f = Foo(x: 10)
var b = Bar(foo: f)
f.x = 30
doAssert b.foo.x == 30

The var keyword isn't valid in a type declaration context. If there is a need of nested mutable objects, you just need to declare the root one with var rather than with let, but not in the type declaration.
Here's how to do that:
type
Foo = object
x: int
type
Bar = object
foo: Foo
var f = Foo(x: 10)
var b = Bar(foo: f)
b.foo.x = 123
echo b

Related

How to use a set comprehension for the body of a function

Suppose I have the following signatures:
sig A {}
sig B {}
sig P {
a: A,
b: B
}
How can I write a function f, say, such that f returns the set of P for which each member has the value x: A for its a field?
Entering the expression {p: P | p.a = x} into the evaluator gives me back a set, but when I try to define f in this manner
fun f(a: A) : set P {
{ p: P | p.a = a }
}
alloy tells me I've made an error:
A type error has occurred
This cannot be a legal relational join where
left hand side is p (type = {this/P})
right hand side is a (type = {this/A})
The problem is that you shadowed the a relation with your function parameter. It works if you replace f(a: A) with f(a': A). Alternatively, you can use the # operator, which returns the global instead of local value of a set:
fun f(a: A) : set P {
{ p: P | p.#a = a }
}

Having trouble creating arbitrary new Object, parametrized for function call

I wanted this kind of expression in OCaml
let wrapper obj f = fun raw -> f (new obj raw)
But I get a compiler error of Unbound class obj but so what, why isn't the compiler satisfied with creating this function which just says call a function on this object which happens to take one init arg.
Pass a function that constructs the object. For a one-argument class foo you can use new foo to get that function.
let wrapper make_obj f raw = f (make_obj raw)
class foo (x) = object
method y = x + 1
end
let answer = wrapper (new foo) (fun o -> o#y) 2
Here, wrapper has a very general type that doesn't mention objects at all. If you want to make it clear that an object constructor is expected as the argument, you can restrict the type with an annotation:
let wrapper (make_obj: (_ -> < .. >)) f raw = f (make_obj raw)
One way to look at this is that an OCaml class is a type, not a value. So you can't write a function in OCaml that accepts a class as a parameter.
Here's a session:
$ ocaml
OCaml version 4.02.1
# class abc = object method m = 12 end;;
class abc : object method m : int end
# abc;;
Error: Unbound value abc
# let f (x: abc) = x#m ;;
val f : abc -> int = <fun>
# f (new abc);;
- : int = 12
As you can see, abc is a type. Not a value.
In other languages, classes are values. But not in OCaml.

Program doesn't compile when "concept" defines a method with a parameter

I have a concept like this:
type Foo = concept x, y
x.test(y) is bool
And then a type that tries to define a method that implements the concept:
type Bar = object
s: string
proc test(x: Bar, y: string): bool =
x.s == y
And a type that has a generic field T: Foo with a constructor that receives a T: Foo:
type Baz[T: Foo] = object
f: T
proc make[T: Foo](f: T): auto =
result = Baz[T](f: f)
When I create a new Bar and pass it to the make proc to make a new Baz, it doesn't compile:
let bar = Bar(s: "whatever")
let made = make[Bar](bar)
Error: type mismatch: got (Bar) but expected 'T'
However it compiles if I drop the y in the concept, like x.test is bool and update the test proc accordingly.
What am I doing wrong?
Change
type Foo = concept x, y
x.test(y) is bool
To
type Foo = concept x
x.test(string) is bool
In your code, it means x and y are both Foo type. If you really means that, please try this.
proc test(x: Bar, y: Bar): bool =
x.s == y.s

How to compare two typedesc in a template for equality

I'd like to be able to compare two typedesc in a template to see if they're referencing the same type (or at least have the same type name) but am not sure how. The == operator doesn't allow this.
type
Foo = object
Bar = object
template test(a, b: expr): bool =
a == b
echo test(Foo, Foo)
echo test(Foo, Bar)
It gives me this:
Error: type mismatch: got (typedesc[Foo], typedesc[Foo])
How can this be done?
The is operator helps: http://nim-lang.org/docs/manual.html#generics-is-operator
type
Foo = object
Bar = object
template test(a, b: expr): bool =
#a is b # also true if a is subtype of b
a is b and b is a # only true if actually equal types
echo test(Foo, Foo)
echo test(Foo, Bar)

Polymorphic object update in OCaml

I want to achieve a system, where objects are polymorphic over their field's contents and that content can be changed. I.e. an object offers a generic way to exchange field f with value a of type a_t with a value b of type b_t for every field f.
A first attempt would be something like this:
class ['a] not_working (a : 'a) = object
val _a = a
method field_a = _a
method modify_a new_a = {< _a = new_a >}
end
This is not polymorphic enough, as the type of not_working is:
class ['a] not_working : 'a -> object ('b) val _a : 'a method field_a : 'a method modify_a : 'a -> 'b end
i.e. the modification yields an object of the same type.
My workaround is the following:
class ['fields_t] the_class (fields : 'fields_t) = object
method field_a = fields#field_a
method field_b = fields#field_b
end
let modify_field_a instance new_a = new the_class (object method field_a = new_a ; method field_b = instance#field_b end)
let modify_field_b instance new_b = new the_class (object method field_a = instance#field_a ; method field_b = new_b end)
let instance = new the_class (object method field_a = 1 ; method field_b = "foo" end)
let mod_instance = modify_field_a instance "1"
I generate a modification function for every field in the_class and this modification function updates this field and copies all others. This is quite noisy.
Is there a way to use the object copy operator or a comparable construct in a similar manner to reduce the boilerplate?
I don't think that you can do what you're after with objects, as I think that would involve a non-regular recursive type:
type 'a foo = < modify: 'b. 'b -> 'b foo >
Note the error message if you try to define that type:
Characters 4-42:
type 'a foo = < modify: 'b. 'b -> 'b foo >;;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: In the definition of foo, type 'b foo should be 'a foo
You might have better luck using records (or first-class modules):
# type ('a, 'b) foo = { a: 'a; b: 'b };;
type ('a, 'b) foo = { a : 'a; b : 'b; }
# let new_foo a b = {a; b};;
val new_foo : 'a -> 'b -> ('a, 'b) foo = <fun>
# let modify_a r new_a = { r with a = new_a };;
val modify_a : ('a, 'b) foo -> 'c -> ('c, 'b) foo = <fun>
# let modify_b r new_b = { r with b = new_b };;
val modify_b : ('a, 'b) foo -> 'c -> ('a, 'c) foo = <fun>

Resources