Re: Problem with UI notification system
I edited my response above :-) > the user checks which type of action it is, before it tries to access any > fields Yeah. This is the crux of the problem. There is no other way around it. The key is making that check as robust as possible so it doesn't blow up when you don't expect it to :-) In Nim, that basically means Variant types + case statements.
Re: Problem with UI notification system
That problem is true with python dictionaries too, btw. I think it's up to the user to know which fields to deal with. Or at least I'm running with that notion, that the user checks which type of action it is, before it tries to access any fields. For example: proc handle_actions() = var action:Action while messenger.poll_actions(action):# loop the stack case action.kind of CellChangeSize: resize_cells( action.dir ) of LayerAddRemove: layer_add_rem( action.add ) of LayerToggleVisible: layer_toggle_vis( action.vis ) of LayerRename: layer_rename( action.new_name ) of LayerChangeAlgo: layer_change_algo( action.algo ) else:discard Run
Re: dynamic lib works properly when interfacing with python, fails with nim
Yeah I jumped the gun... after some further testing it was just luck python was returning a 0. @Araq it's a closed source dll to make this even more annoying, but the functions are being exported as `stdcall` as far as I've been told. I set up this test. Delphi dll code: library wrapd; uses System.SysUtils; {$R *.res} function OpenDataFile(FileName: PChar): int32; stdcall; begin WriteLn(FileName); WriteLn('test test test'); Result := 99; end; exports OpenDataFile; end. Run nim code: proc OpenDataFile(filename: cstring): int32 {.stdcall, dynlib: "wrapd.dll", importc.} let fpath: cstring = r"C:\Users\okapi210\Desktop\test.file" var fhandle = OpenDataFile(fpath) echo fhandle Run result: ?e test test test 99 Run So passing a cstring to PChar isn't working I probably just need a byte array
Re: Problem with UI notification system
Templates are very powerful, and it's cool that Nim can do this. Nim is all about flexibility :-) > in case an empty Action is needed, or to not have to type the whole > properties: %*{} thing (might be redundant, I was just trying out things and > stumbled on that. Still trying to grasp templates). Yes. You could make your own template that does the Actions( properties:... ) stuff for you. # I used &&, but you could use whatever you wanted. template `&&`(fields: untyped): untyped = Action( properties: %*`fields` ) var a2 = &&{ "layer": 1, "add": true, "vis": false, "new_name": "woohoo less typing!" } Run But, here are some examples on why the json dictionary type is not as type safe (dynamically typed): # assume all the code @mratsim wrote above is included proc doSomething(a: Action) = if a.Foo != 42: echo "sorry, not the answer to the universe" var a1 = Action( properties: %*{ "foo" = 10 } ) var a2 = Action( properties: %*{ # oops, I'm missing `foo` "bar" = "I'm a string" } ) var a3 = Action( properties: %*{ "foo" = "oops, I'm a string now!" } ) doSomething(a1) # cool doSomething(a2) # uh-oh, I don't a have a bar, but the compiler won't tell me, I will get a run time Exception! doSomething(a3) # even worse! I won't get any error, but the result will be wrong! a3.foo will be interpreted as 0 and just keep going! Have fun debugging this one in a large program. Run A Variant type on the other hand will yell at you at compile time that the variant is either missing the field or the field is the wrong type. As far as the fix for Variant types go: I don't really care what syntax we end up going with, but I do hope it will get fixed eventually. It's more of an inconvenience imo. Variant types are still usable and capable without this feature!
Re: Problem with UI notification system
Well meanwhile I managed to find [a bit of a workaround](https://gist.github.com/Skaruts/11c9b4b8af153c5a4664eb46300455f4) for not being able to have attributes with the same name, for another part of my project.
Re: Problem with UI notification system
@rayman22201 indeed I wasn't thinking of anything that isn't type safe or outside of Nim's phylosophy. What @mratsim did above (1st post) with templates and the JSON module is what got me wondering, since it's actually not that far away from behaving like a python dictionary, from the POV of the user. # Correction: it's actually closer to the behavior of GDScript dictionaries, # since afaik python doesn't allow creating dict fields like: a.foo = 10 # only like: a["foo"] = 10 Run
Re: Macro to create a dictionary (table) like in python!
{} is a sugar for array of tuples, so @ already works with it by just making a sequence. echo @{"key_1": "value_1", "key_2": "value_2"} Run results in @[("key_1", "value_1"), ("key_2", "value_2")] Run
Re: Macro to create a dictionary (table) like in python!
I would have to agree with `@`. +1 vote.
Re: dynamic lib works properly when interfacing with python, fails with nim
It could also be something else, of course. But `ctypes` could get lucky with the stack layout and Nim doesn't.
Re: Nim vs V language
> [It](https://github.com/vlang/v) has 1k more Github stars than > [Nim](https://github.com/nim-lang/Nim). Yet another reminder that [GitHub stars are an awful harmful way to measure](https://old.reddit.com/r/nim/comments/8q99ba/happy_5000_stars/e0i7etu/) anything... > BTW, Nim is approaching 1000 nimble modules!
Re: Macro to create a dictionary (table) like in python!
I think using @ instead of the % is perfect. Its just like the array syntax. var a = @[1, 2, 3] var b = @{"key_1": "value_1", "key_2": "value_2"} Run
Re: dynamic lib works properly when interfacing with python, fails with nim
How does the python's ctypes work? ctypes supports register calling convention?
Re: Problem with UI notification system
@mratsim's solution is very good for prototyping, and probably what you want. The Json module is the recommended way to get python dictionary behavior in Nim. It's the generally recommended way to transition Python programmers to Nim :-P > if one couldn't come up with a Nim implementation of the exact behavior of > python dictionaries? But, a native Python dictionary is probably never going to be put in the std library. Nim is a **statically typed language** , and this is dynamic behavior! You are setting the types of the dictionary at runtime. This is against the philosophy of statically typed languages like Nim. Dynamic types like this have a cost. It's still much faster than Python, but it isn't free, and you loose most of the Nim type safety. Variant types like in your initial post is the most idiomatic Nim, type safe way to do it. In fact, this is how Nim does it for the compiler: [https://nim-lang.org/docs/manual.html#types-object-variants](https://nim-lang.org/docs/manual.html#types-object-variants) Unfortunately, as @doofenstein pointed out, you have hit a limitation of variant types in the current Nim. Either every variant that shares a field must be grouped together, or each variant must have a different field name. This is slightly inconvenient, I agree, and the proposed fix has stalled unfortunately (bigger fish to fry in the compiler). The advantage of variant types is that the compiler can warn you at compile time if you attempt to access a field on an Action that doesn't exist for that action type. You won't get that with a Dictionary. You (or your user) will get a run time error instead (this is the point of static types). One strategy may be to use the Json dictionary while you are prototyping, then once you have a better idea of what fields you need on each Action type, swap it out for a Variant type. Personally, I prefer to just use Variant types up front, because it lets me more clearly design my data types, and lets the compiler help me (by yelling at me) if I forgot a field somewhere.
Re: Problem with UI notification system
looking at the problem as you detailed it in your first post it seems like you're searching for a way to have variant object, where fields are shared between specific cases. There has been [discussion](https://github.com/nim-lang/RFCs/issues/19) to implement this, though they've come to a standstill. What other have suggested is making the fields completely dynamic, which is not ideal, since it undermines type safety and is slower than a simple field. Though in this case it's probably the best solution.
Re: Problem with UI notification system
There's a lot to take in in this, and I'm understanding some of it, but I'll take some more time to see if I can grasp it mostly. There's quite a few things that are new or still mysterious to me. I noticed I can sort of shortcut it with template action():untyped = Action( properties: %*{} ) var a = action a.algo = 10 echo a.algo# 10 Run in case an empty Action is needed, or to not have to type the whole **properties: %*{}** thing (might be redundant, I was just trying out things and stumbled on that. Still trying to grasp templates). Meanwhile, I am wondering -- and this is just a curiosity; I don't intend to explore this path myself -- if with some clever use of templates like this, and assuming one can overload the {} operators to this end, if one couldn't come up with a Nim implementation of the exact behavior of python dictionaries? # basically so that one could do just this: let a = { some_str:"bla bla", some_int:10 } # or like this var a = {} a.derp = 10 a.depier = "the derpest" Run
Re: Macro to create a dictionary (table) like in python!
is sugar, so a literal is also possible.
Re: Problem with UI notification system
They allow rewriting a field access or field assignment call to the `Action` type to something else, there is more detail in the manual: [https://nim-lang.org/docs/manual_experimental.html#special-operators-dot-operators](https://nim-lang.org/docs/manual_experimental.html#special-operators-dot-operators). In the example I'm using the template to instead access a properties json field and make those access/assignments feel seamless. There is a remaining issue that the type returned is a `JsonNode` so in practice you would need: a.new_name.getStr() # extract the string from the JsonNode a.algo.getInt() # extract the int from the JsonNode Run If you want truly seamless calls without the need of `getStr` you would need something like the following, note the doAssert on the return type to make sure we don't get JsonNodes, and we don't need the . experimental template either: import json type Action = ref object properties: JsonNode template addPseudoField(A: typedesc, field: untyped, T: typedesc) = # A is for the type namespace (Action) template getType(args: varargs[untyped]): untyped = # Alias the JsonNode getType function when T is string: getStr(args) elif T is int: getInt(args) elif T is bool: getBool(args) elif T is float: getFloat(args) else: # You can add your own type special marshaller/deserializer raise newException(ValueError, "Unsupported type: " & $T) proc `field`*(a: A): T = a.properties[astToStr(field)].getType() proc `field=`*(a: A, val: T) = a.properties[astToStr(field)] = %val Action.addPseudoField(layer, int) Action.addPseudoField(add, bool) Action.addPseudoField(vis, bool) Action.addPseudoField(new_name, string) Action.addPseudoField(algo, int) var a = Action( properties: %*{ "layer": 0, "add": true, "vis": false, "new_name": "fancy_name" } ) echo a.new_name # "fancy_name" a.algo = 10 echo a.algo # 10 doAssert a.algo is int doAssert a.new_name is string Run
Re: Problem with UI notification system
Hmm, I was just now reading about the JSON module and contemplating using it. Thanks for the examples. I don't understand what the templates do though.