I spent a few hours making a library seeing how far I could push things with 
dynamic typing. I ended up making a type called `DynVal` that's basically a box 
for all primitives and ref values inheriting from RootObj. It uses converters 
and operator overloads to make DynVal usable in any place where a primitive or 
string is used, including all the fun things like type coercion from strings to 
various primitive values.

I started doing this while playing around with the dot call operator overload 
experimental feature, which I used to make a table where you could access and 
call properties as if they were procs.

Here's my dynamic typing code: <https://git.termer.net/termer/nim-dynval>

You can look at the README and tests to see what it can do.

What's missing is the actual thing I started out trying to do: accessing and 
assigning arbitrary properties and calling procs dynamically. The dynamic 
properties is easy, all I need to do is have a Table of strings mapping to 
`DynVal`, but the proc thing is a little trickier. The call signature would 
need to be something like `proc (args: varargs[DynVal])` to allow passing in 
any params, and then a macro would need to be used to generate type guards for 
any procs you assign.

For example, doing the following:
    
    
    myDynVal.yellName = proc (name: string): string = name.toUpper() & '!'
    
    
    Run

...would need to wrap the proc in the something like the following:
    
    
    proc yellNameWrapper(args: vararg[DynVal]): DynVal =
        if args.len < 1:
            raise newException(TypeError, "Expected 1 argument but got 0")
        
        var nameArg = args[0]
        if nameArg.kind != dvkString:
            raise newException(TypeError, "Expected argument 1 to be of type 
string")
        
        return newDynVal(yellName(nameArg.dynValString))
    
    
    Run

I don't know if macros have introspection ability for procs. If they can 
retrieve a proc's argument list and return type, then it should be possible.

The other thing I ran into is the fact the compiler doesn't like generic 
converters, and can't really make use of them to implicitly convert. Type 
inference isn't possible without arguments, so you can't infer what a 
converter's generic type should be based on the proc you're putting the value 
into. This makes it a lot less ergonomic.

Reply via email to