There are various libraries in nim that return actual objects, rather than references. Sometimes I want an object on the heap (regardless of efficiency) -- for instance when I have a generic procedure that expects a ref to an object.
The only way to construct an IntSet on the heap I have found is:
proc newIntSet() : ref IntSet =
new(result)
assign(result[], initIntSet())
This seems to work, but feels like a hack. I worry if it only seems to work. (Are the structures copied by "assign" properly cleaned up?) Is there a better way? Is there a more generic way that will work with other objects?
Your code is perfectly valid. The resulting reference will be subject to garbage collection as any other referefence.
If you find yourself doing this often, you can define the following makeRef template to get rid of the code repetition:
template makeRef(initExp: typed): expr =
var heapValue = new(type(initExp))
heapValue[] = initExp
heapValue
Here is an example usage:
import typetraits
type Foo = object
str: string
proc createFoo(s: string): Foo =
result.str = s
let x = makeRef createFoo("bar")
let y = makeRef Foo(str: "baz")
echo "x: ", x.type.name, " with x.str = ", x.str
Which will output:
x: ref Foo with x.str = bar
Related
Here's a psuedocode implementation of what I would be looking for within Julia:
struct Example
field1::Float64
field2::Float64
end # End struct
example = Example(1., 2.)
function modifystruct(mystruct, fieldname)
mystruct.fieldname +=10
return mystruct
end
modifystruct(example, field1)
# In this instance I would want to have example.field1 = 11.
How would I actually do this? I want to provide the fieldname as something like a string, and have my struct."whateverfieldname" get modified as such. I should add that I do NOT want to code something in like this:
function modifystruct(mystruct, fieldname)
if fieldname = "fieldname1"
mystruct.field1 +=10
end
if fieldname = "fieldname2"
mystruct.field2 +=10
end
return mystruct
end
Largely due to how versatile I want this code to be. I may be using different types of structs for my program, so the closest I can get to directly accessing by the name of the field, the better. Is there any method or implementation that can do this for me?
Sure, that's setproperty!(value, name, x) and getproperty(value, name):
function modifystruct(mystruct, fieldname)
new_field = getproperty(mystruct, fieldname) + 10
setproperty!(mystruct, fieldname, new_field)
return mystruct
end
As DecowVR rightly notes, this requires mystruct to be mutable.
If you want to do this repeatedly and with nested properties, you might be interested in lenses such as those provided by Setfield.jl.
Firstly, whould be noticed that in order to be able to modify an struct, it needs to be mutable:
julia> mutable struct Example
field1::Float64
field2::Float64
end
julia> example = Example(1., 2.)
Example(1.0, 2.0)
And now, a simple aproach would be to use Julia Symbols. A symbol is nothing else but an expression like :var. Can be used as shown:
julia> example.:field1
1.0
However, if we create a variable that stores the symbol, it won't work:
julia> v = :field1
:field1
julia> example.v
ERROR: type Example has no field v
Stacktrace:
[1] getproperty(x::Example, f::Symbol)
# Base ./Base.jl:42
[2] top-level scope
# REPL[18]:1
This is due to the order in which the Julia Interpreter works. If we want to evaluate firstly the variable, and then the expression, it is as easy as:
julia> #eval example.$v
1.0
So the complete function would be as follows:
julia> function modify_struct(mystruct::Example, fieldname::Symbol)
#eval $mystruct.$fieldname += 10
end
I'm trying to better understand reasoning behind the value types.
Does value/reference types in Nim works same way as in Swift?
yes, value and reference types do work in Nim as in Swift and other low-level programming languages like C#, C++, Rust. By that I mean that they follow these semantics with respect to copy:
Value semantics means that the copy owns its memory and lives separately from the copied.
Reference semantics means that the copy and the copied refer to the same underlying memory location.
(taken from this forum answer).
As an example, I translate this swift blog post to nim (playground):
# port of https://developer.apple.com/swift/blog/?id=10 to Nim
## Example of Value type
type S = object
data: int # I cannot say the default of data is -1. Nim does not have (yet) custom initialization, see accepted RFC https://github.com/nim-lang/RFCs/issues/252
var a = S()
var b = a
a.data = 42
echo (a, b) # ((data: 42), (data: 0))
## Example of Reference type
type C = ref object
data: int
func `$`(c: C): string = "C(data: " & $(c.data) & ")" # there is no default $ for ref objects as there is for objects
var x = C()
var y = x
x.data = 42
echo (x, y) # (C(data: 42), C(data: 42))
Note that:
Nim does not have a copy-on-write mechanism for value types as in Swift (but you can build your own CoW type)
Nim does not have a === operator like Swift (see this discussion).
Can I use PureScript types in JS? For example:
type SomeType = /*type declaration*/
func :: SomeType
func = /*type construction*/
And then in JS do something like this:
let a = module.func()
a instanceof module.SomeType === true
If not if there is any Haskellish language where I can achieve it (Elm, GHCJS, Idris?)?
In general the answer is "no". The runtime representation really depends on what the type is exactly.
For data declarations, every constructor would be represented by a JS "class", like this:
-- PureScript:
data T = A Int | B
x :: T
x = A 42
// JS:
function A(value0) { this.value0 = value0; }
A.create = function(value0) { return new A(value0); }
function B() { }
B.value = new B();
var x = A.create(42);
So you can technically use instanceof to distinguish between cases, but not to determine the type itself.
For a newtype, on the other hand, the type wrapper will be completely erased, because that's the whole point of newtype:
-- PureScript:
newtype T = T Int
x :: T
x = T 42
// JS:
var x = 42;
And for type synonyms (declared with the type keyword), there is no distinct representation. That is, the way such types are represented at runtime is the same as their right-hand side representation:
-- PureScript
type T = Int
x :: T
x = 42
// JS:
var x = 42;
This also applies to naked records, because they are merely type synonyms too:
-- PureScript
type R = { x :: Int, y :: String }
r :: R
r = { x: 42, y: "foo" }
// JS:
var r = { x: 42, y: "foo" }
So the bottom line is: there is no good way to do this. PureScript simply makes no promises about runtime representation. It makes very good promises about program behavior, but not about how it would be implemented in JS (or whatever other backend you happen to be using).
And this is another problem: because PureScript doesn't make any promises like that, it's a very bad idea to rely on your (mine) knowledge of the current implementation, because the next version of the compiler may change it completely. PureScript can do this, because it made no promises. See how that works?
For example, I know there is a pull request in the pipeline somewhere that would switch data representation to arrays, like this:
-- PureScript:
data T = A Int | B
x, y :: T
x = A 42
y = B
// JS:
var x = ["A", 42]
var y = ["B"]
If this pull request is ever accepted, your program will be broken.
In conclusion I can also tell you that neither Elm, nor Haskell, nor Idris will exhibit the property you're after. Runtime type information is generally not a thing valued in the ML universe. One can argue it's effectively present in Idris, in a way, but not in the way you expect.
You may want to try F#/Fable: it's a little bit stronger in this regard, but still not as good as on its native .NET runtime. I don't think you can just check types of F# objects from JS out of the blue, but I know that Fable does support accessing RTTI from F# itself (at extra performance cost), so you can at least make functions to do that and export them to JS.
If you can expand a bit on what your actual problem is, then perhaps I (or someone else) would be able to suggest an alternative solution.
Control.Lens.Setter is remarkable to use Observable feature in Haskell. ( function/functor to be triggered when the value in the dataset is updated. )
However, considering the lens is not included in the standard environment, and then required to extra installation, without the lens, when I want to use just a primitive setter feature such as with a field label:
data Foo = Foo {val :: Int}
How to do this?
Does ST Monad fit this purpose?
Thanks.
It's not very clear what you're looking for here, but if you just want to update a record field, you can use the Haskell record update syntax:
x = Foo { val = 5 }
y = x { val = 42 }
This works for any record, with any number of fields, and you don't need to list all the fields, only the ones you'd like to update, for example:
data D = D { a :: String, b :: Int }
x = D { a = "foo", b = 42 }
y = x { a = "bar" } -- now y = D { a = "bar", b = 42 }
z = x { b = 43 } -- now z = D { a = "foo", b = 43 }
Keep in mind that this doesn't actually update ("change", "mutate") the values in memory, but rather creates copies of the records with all the fields equal to those of the original record, except the updated fields. Lenses work the same way, and in fact everything in Haskell does, since Haskell doesn't allow mutation at all.
I think that you're a bit confused between a few concepts; specifically, setter vs observable.
I don't know much about them, but an observable does seem to be, as you described, a way to run a function every time a value is changed. This concept does not exist in Haskell; I'm sure you could make it somehow, but it wouldn't be very useful, since (almost) every Haskell value is immutable.
By contrast, a setter is just a function which changes part of a value, the same as with Java getters and setters. The only slight complication is that in Haskell, all values are immutable (as I mentioned above), so instead of changing the value, a setter copies the value across but with the thing set. For instance, if you have a setter setName (for a record), and you invoke it with something like setName "foo" oldRecord, this will keep oldRecord as is, but return a new record with the name set to "foo". As you already know, there are other, more complex, implementations of setters, such as lenses.
You also mention ST. This is a more advanced concept; it's basically used when you have to use some sort of mutable variable locally but still retain purity (which is not very often).
Now to answer your other question: How do I use setters without lenses? Well, if you have a record like data Foo = Foo {val :: Int, val2 :: String} (your example + an extra field), and you have an old record - let's say oldRecord = Foo { val = 1, val2 = "test" }, Haskell has special setter syntax: doing oldRecord { val = 2 } will give a new record with val set to 2 - that is, it will give Foo { val = 2, val2 = "test" }. Obviously this syntax is a bit clumsy though for nested records, which is the reason lenses were invented.
Consider a type hierarchy, where the base object is non-generic, but sub-types are:
type
TestBase = ref object of RootObj
DerivedA = ref object of TestBase
DerivedB[T] = ref object of TestBase
field: T
proc testProc(x: TestBase) =
if x of DerivedB: # <= what to do here
echo "it's a B!"
else:
echo "not a B"
Using the of operator like this won't compile, because it expects object types. What does work is e.g. to match for specific types like DerivedB[int], or making the proc itself generic in T, which is meaningless when passing in a DerivedA.
Is there a way to solve this problem generically without resorting to methods and dynamic dispatch?
The easiest solution here is to introduce a dummy base type for all of the generic derived types, with the only purpose of assisting in such checks. Here is an example:
type
TestBase = ref object of RootObj
DerivedA = ref object of TestBase
# I'm using illustrative names here
# You can choose something more sensible
DerivedDetector = ref object of TestBase
DerivedB[T] = ref object of DerivedDetector
field: T
proc testProc(x: TestBase) =
if x of DerivedDetector: # This will be true for all derived types
echo "it's a B!"
else:
echo "not a B"
testProc DerivedB[int](field: 10)
testProc DerivedA()
This solution won't increase the size of the objects and it doesn't introduce any run-time overhead in typical code.
If you can't modify the inheritance hierarchy (it may be part of a third-party library), there is a much more complicated solution based on the getTypeInfo proc from the system module. This proc returns an opaque pointer that can be used as an identifier for the type. You'll have to register all derived types with their identifiers in a hash table (you can do this at the start of the program) and then use that to make run-time checks against the type-info pointers of the input values in the proc.