Nim-lang: OOP features supported? - oop

While learning basics of Nim-lang,
I have read that the OOP is minimalistic in Nim;
But I would like to know what features are exactly supported?
Like:
Over-ride.
Over-load (not supported by PHP yet, 2022).
Multi-inheritance (except C++, not supported by any language?).
Generics.
Classes.
Namespaces.
Import-as/from-namespace (or Include-file-content like C/C++).
Custom type-defs (name aliases).
Custom operator implementation(s).
Traits (saw only in PHP, if this is even OOP?).

BTW, most of the items on this list aren't OOP specific or even related to the OOP paradigm
However, Nim does support:
Over-ride.
Over-load.
Generics.
Import-as/from-namespace (or Include-file-content like C/C++).
Custom type-defs (name aliases).
Custom operator implementation(s).
Nim does not have:
Multi-inheritance.
Traits.
Nim weakly supports:
Classes.
Where Polymorphism only really works on ref types.
Namespaces.
This should be in not-supported list,
but you can force it to use an empty type as the first argument,
or store everything in a variable and don't export anything.

Related

Accessing Windows Contacts (pre Win10) from JScript (or any ActiveScripting)

I want to use the COM object with the progID Windows.Contact.1 via ActiveScripting (JScript, VBScript, Python, etc).
This COM resides in C:\Program Files (x86)\Common Files\System\wab32.dll. It seems, there is no TypeLib available for it. The COM delivers, amongst others, IContact for the "Windows Address Book" (storing contacts as XML in folders, as in Windows 7). IContact is documented here.
In JScript I did:
var co = new ActiveXObject("Windows.Contact.1");
typeof co; // results in: unknown
Since it results in unknown, I have the suspicion, that this COM could not be usable for scripting. Somewhere I read, that everything, that inherits from IUnknown can not be used for scripting, instead it must inherit from IDispatch. But I am unsure, as to how much of this is valid, and whether there are workarounds.
I would like to ask for acknowledgement of my suspicions (since I am new to all of this and have no C++ or C# background) or to ask for a way, as to how to use Windows.Contact.1 from scripting, including a way, to find out, which methods/objects I can use, without resorting to a TypeLib.
I have access to pages like Programming Windows Contacts and related ones, but first I need to get an instance in ActiveScript (JScript, VBScript, Python, Lua will do). I also have access to applications like "MS OLE View" and "OLEView DotNet". Thank you.
There are entire books on the subject, but here's a very simplified story. There are basically 3 "categories" of COM interfaces:
Interfaces deriving from IUnknown
aliases for programming against: early binding, (custom) vtable binding
the simplest way to implement a COM "server"
it's only a binary contract (methods layout, method signature, parameters behavior like in/out for cross-apartment/process support, ...)
you need to somewhow tell your callers what is this binary contract you support (you can use .idl, .tlb or anything that your caller can understand)
there are some official ways of documenting your IUnknown-derived interfaces: .idl -> .h and .tlb is the most standard one
only supported by a certain class of languages (for example C/C++, .NET, Delphi), those who understand .tlb (or .idl, or equivalent .h), or those who allow redefining layout manually (like .NET). You can perfectly define a language that can do that w/o ever using .tlb. That's the beauty of COM, it's just a binary contract.
if your language doesn't support it, you just can't use it, you'll have to write or use a wrapper with a language that supports it and exposes it in a way your language supports. Powershell for example doesn't support IUnknown-derived interfaces (I'm not 100% sure) but supports .NET so it can use .NET as a "super wrapper".
IDispatch interface
only requires one IUnknown well-known interface implementation: IDispatch
aliases for programming against: late binding, OLE automation, COM automation, or simply Automation (not to confuse with UI Automation)
invented for higher level languages (VB/VBA first, ActiveScripting a bit later)
only supported by a certain class of language, and the way it's supported varies (for example it's supported in C++ of course but it's not super easy w/o wrappers or tooling like Visual Studio's C++ #import directive). JScript and VBScript don't exactly support the same set of features with regards to Automation.
you're supposed to use only a predefined list of types "Automation-Compatible types":
these types where initially very related to VB/VBA (VARIANT, SAFEARRAY, BSTR which means "Basic String"...)
from the higher level language, it really makes COM much transparent and easier as that was the whole point (and can make it harder from the lower level ones...), it also allows "syntactic sugar" niceties
note the IDispatch implementation can be very dynamic and really late-bound at runtime (get id of name -> invoke) but most available programming tooling quite freezes the list of ids/names at compile time (ex: .NET) because they support Dual interfaces.
Dual interfaces:
interfaces that implement a custom IDispatch-derived interface and implement IDispatch itself to match the custom interface (both implementations supposedly being "equivalent" of course). Have a look at the link below, it has nice images.
because of IDispatch, you're supposed to use only Automation compatible data types in the IDispatch-derived method.
it's more work to implement (so it's usually done by programming tools, for ex: ATL)
a bit easier for native (C/C++, etc.) callers (no need to use IDispatch wrappers) but you still have to digest automation data types
IMHO, one of the best 1-page introduction to COM is here: Introduction to COM

Is C++/CLI an extension of Standard ISO C++?

Is Microsofts C++/CLI built on top of the C++ Standard (C++98 or C++11) or is it only "similar" and has deviations?
Or, specifically, is every ISO standard conforming C++ program (either C++98 or C++11), also a conforming C++/CLI program?
Note: I interpret the Wikipedia article above only comparing C++/CLI to MC++, not to ISO Standard C++.
Sure, it is an extension to C++03 and can compile any compliant C++03 program that doesn't conflict with the added keywords. The only thing it doesn't support are some of the Microsoft extensions to C++, the kind that are fundamentally incompatible with managed code execution like __fastcall and __try. MC++ was their first attempt at it, kept compatible by prefixing all added keywords with underscores. The syntax was rather forced and not well received by their customers, C++/CLI dropped the practice and has a much more intuitive syntax. Stanley Lippman of C++ Primer fame was heavily involved btw.
The compiler can be switched between managed and native code generation on-the-fly with #pragma managed, the product is a .NET mixed-mode assembly that contains both MSIL and native machine code. The MSIL produced from native C++ source is not exactly equivalent to the kind produced by, say, the C# or VB.NET compilers. It doesn't magically become verifiable and doesn't get the garbage collector love, you can corrupt the heap or blow the stack just as easily. And no optimizer love either, the MSIL gets translated to machine code at runtime and is optimized just like normal managed code with the time restrictions inherent in a jitter. Getting too much native C++ code translated to MSIL is a very common mistake, the compiler hides it too well.
C++/CLI is notable for introducing syntax that got later adopted into C++11. Like nullptr, override, final and enum class. Bit of a problem, actually, it begat __nullptr to be able to distinguish between a managed and a native null pointer. They never found a great solution for enum class, you have to declare it public to get a managed enum type. Some C++11 extensions work, few beyond the ones it already had, auto is fine but no lambda expressions, quite a loss in .NET programming. The language has been frozen since 2005.
The C++/CX language extension is notable as well, one that makes writing C++ code for Store and Phone apps palatable. The syntax resembles C++/CLI a great deal, including the ref class and hats in the syntax. But with objects allocated with ref new instead of gcnew, the latter would have been too misleading. Otherwise very different from C++/CLI at runtime, you get pure native code out of C++/CX. The language extension hides the COM interop code that's underneath, automatically reference-counting objects, translating error codes into exceptions and mapping generics. The resemblance to C++/CLI syntax is no accident, they basically perform the same role. Mapping C++-like syntax to a foreign type system.
CLI is a set of extensions for standard C++. CLI has full support of standard C++ and adds something more. So every C++ program will compile with enabled CLI, except you are using a CLI reserved word and this is the weakness of the extension, because it does not respect the double underscore rule for extensions (such reserved words has to begin with __).
You can deactivate those extensions in the GUI by:
Configuration Properties -> General -> Common Language Runtime Support
Even Bjarne Stroustrup calls CLI an extension:
On the difficult and controversial question of what the CLI binding/extensions to C++ is to be called, I prefer C++/CLI as a shorthand for "The CLI extensions to ISO C++". Keeping C++ as part of the name reminds people what is the base language and will help keep C++ a proper subset of C++ with the C++/CLI extension
Language extensions could always be called deviations from the standard, because it will not compile with a compiler without CLI support (e.g. the ^ pointer).

How would you implement a toString method, on the base class, if the string class inherits from the base class?

In many modern OOP languages, such as Java and C#, reference types have a base class typically called Object from which all other reference types inherit their core functionality.
These languages also have a universal .toString() method shared across all the reference types, so that it's easy to extract data as a string from it.
Now here's the question: If the String class is a subclass of Object, how can Object implement a .toString() method without causing a circular dependency?
if A uses B and B implements A it's bound to cause problems, or am I totally wrong in this?
Regarding C# (and I'm pretty sure the same goes for Java), the compiler doesn't require that source files be provided in dependency order.
This means that, unlike other compilers (the F# compiler and gcc, I believe), the C# compiler allows you to refer to symbols that haven't been seen by the compiler yet (as long as both types are in the same assembly).
In other words - yes, there's is a circular dependency, but the compiler takes care of that for you. If you want to know how compilers handle circular dependencies, then that has been asked on programmers.stackexchange already.

What OCaml standard library types cannot be marshalled?

I have a failure Marshaling a data structure (error abstract type (Custom)). There is one known abstract type in use, namely Big_int. However that Marshals fine. There is no custom C code in the application. Apart from Nums, Unix library is also used (however I don't believe there are any active objects of that type). We're Marshal'ing with Closures.
Two (only) third party libraries are in use: OCS Scheme (Scheme interpreter, pure Ocaml) and Dypgen (extensible GLR parser, also pure Ocaml). The problem is with a new feature of Dypgen, saving a dynamically extended parser.
The Ocaml error message is next to useless (it doesn't identify which abstract type with Custom tag is the culprit).
We suspected Lexbuf as the culprit because it contains a closure over an Ocaml channel, and can't be Marshal'ed, but it seems this isn't the problem. So my question is:
Which standard library components can't be Marshall'd?
Weak arrays cannot be marshaled. I am not familiar with OCS Scheme, but I would expect an interpreter for a garbage-collected language written in OCaml to use weak pointers (they let you piggy-back on OCaml's memory management).
In OCaml's defense, I do not think that the Custom method block contains the name of the type (retrospectively, that seems like a good thing to have).
EDIT: Yep:
$ grep Weak ~/Downloads/ocs-1.0.3/src/*.ml
/Users/pascal/Downloads/ocs-1.0.3/src/ocs_sym.ml:module SymTable = Weak.Make (HashSymbol)
EDIT2:
As pointed out by ygrek, there is room for a name in the custom method block. I should also clarify that weak arrays are not custom values, since my answer seemed to imply that. Weak arrays have the Abstract tag and are chained using the first word of data so that the garbage collector can traverse them in special weak-pointer-related phases of the collection cycle.

Why aren't hot-swappable vtables a popular language feature?

In object-oriented programming, it's sometimes nice to be able to modify the behavior of an already-created object. Of course this can be done with relatively verbose techniques such as the strategy pattern. However, sometimes it would be nice to just completely change the type of the object by changing the vtable pointer after instantiation. This would be safe if, assuming you're switching from class A to class B:
class B is a subclass of class A and does not add any new fields, or
class B and class A have the same parent class. Neither do anything except override virtual functions from the parent class. (No new fields or virtual functions.)
In either case, A and B must have the same invariants.
This is hackable in C++ and the D programming language, because pointers can be arbitrarily cast around, but it's so ugly and hard to follow that I'd be scared to do it in code that needs to be understood by anyone else. Why isn't a higher-level way to do this generally provided?
Because the mindset of most languages designers is too static.
While such features are dangerous in the hand of programmers, they are necessary tools for library builders. For example, in Java one can create objects without calling a constructor (yes, you can!) but this power is only given to library designers. Still however, many features that library designers would kill for are alas not possible in Java. C# on the other hand is adding more and more dynamic features in each version. I am really looking forward to all the awesome libraries one can build using the upcoming DLR (dynamic language runtime).
In some dynamic languages such as Smalltalk (and also as far as I know Perl and Python, but not Ruby) it is totally possible to change the class of an object. In Pharo Smalltalk you achieve this with
object primitiveChangeClassTo: anotherObject
which changes the class of object to that of anotherObject. Please note that this is not the same as object become: anotherObject which exchanges all pointers of both objects.
You can do it in Python, by modifying the instance __class__ attribute:
>>> class A(object):
... def foo(self):
... print "I am an A"
...
>>>
>>> class B(object):
... def foo(self):
... print "I am a B"
...
>>>
>>> a = A()
>>> a.foo()
I am an A
>>> a.__class__
<class '__main__.A'>
>>> a.__class__ = B
>>>
>>> a
<__main__.B object at 0x017010B0>
>>> a.foo()
I am a B
However in 12 years of Python programming I have never had a use for it, and never seen anyone else use it. IMHO there is a huge danger that casual use of this feature will make your code hard to maintain and debug.
The only situation where I can imagine using it is for runtime debugging, e.g. to change an instance of a class whose creation I don't have control into a mock object or into a class that has been decorated with logging. I would not use it in production code.
You can do it in higher level languages - see the Smalltalk "become" message. The fact that this feature is almost impossible to use correctly even in ST could be the reason that statically typed languages like C++ don't support it.
To paraphrase the XoTcl documentation, it is because most languages which proclaim to be "object oriented" are not--they are class oriented. It sounds like XoTcl mixins, Ruby mixins, and Perl6 roles provide the functionality you're looking for.
What you're talking about is monkey patching, that is available in several high level dynamic language :
A monkey patch (also spelled
monkey-patch, MonkeyPatch) is a way to
extend or modify the runtime code of
dynamic languages (e.g. Smalltalk,
JavaScript, Objective-C, Ruby, Perl,
Python, Groovy, etc.) without altering
the original source code.