Why isn't my static member function recognised across assemblies? - import

I have a helper assembly which includes a function to identify object types:
namespace Util
{
using namespace System;
public ref class CastingHelpers
{
public:
template < class T, class U >
static System::Boolean isinst(U u);
static bool Test() {return true;}
};
}
...but for some reason, when I try and use it in a gui application which references the assembly:
Util::CastingHelpers::Test();
Util::CastingHelpers::isinst<SomeClass^>(someInstance);
..gives me an error:
2>.\DataProcessor.cpp(161) : error C2039: 'isinst' : is not a member of 'Util::CastingHelpers'
Note that test works fine. Is this something to do with the fact that isinst uses generics?

You are not creating a generic function, you are creating a C++ template function which is not exported from the assembly.
Use the keyword generic instead of template to create .NET generic types and methods.
The template method is only visible by code that #includes its declaration.

Related

Can I use in Google Apps Scripts a defined Class in a library with ES6 (V8)?

I'm trying to use a class defined in a library but I only receive an error as a result.
[LibraryProject]/library/model/Update.gs
class Update {
constructor(obj = {}) {
if(typeof obj == "string"){
options = JSON.parse(obj);
}
Object.assign(this, obj);
}
text(){
return (this.message && this.message.text)?this.message.text:''
}
}
TASKS
✅ Create a new version of the project. (File > Manage versions...)
✅ Load this library in another project [Alias: CustomService] (Resources > Libraries...)
✅ Use functions of CustomService
❌ Use class of CustomService
If I try to use a Class
[NormalProject]/index.gs
function test (){
Logger.log(CustomService.libraryFunction())
var update = new CustomService.Update("");
Logger.log(update)
}
TypeError: CustomService.Update is not a constructor (línea 3, archivo "Code")
How can I instantiate an Object of this Class?
If I run...
Logger
As written in the official documentation,
Only the following properties in the script are available to library users:
enumerable global properties
function declarations,
variables created outside a function with var, and
properties explicitly set on the global object.
This would mean every property in the global this object are available to library users.
Before ES6, All declarations outside a function (and function declaration themselves) were properties of this global object. After ES6, There are two kinds of global records:
Object record- Same as ES5.
Function declarations
Function generators
Variable assignments
Declarative record - New
Everything else - let, const, class
Those in the declarative record are not accessible from the global "object", though they are globals themselves. Thus, the class declaration in the library is not accessible to library users. You could simply add a variable assignment to the class to add a property to the global object(outside any function):
var Update = class Update{/*your code here*/}
References:
Library official documentation
Global environment records
Related Answers:
ES6- What about introspection
Do let statements create properties on the global object
Based on your tests, it appears that you cannot directly import a class from a GAS library. I'd recommend creating a factory method to instantiate the class instead.
Something along these lines:
// Library GAS project
/**
* Foo class
*/
class Foo {
constructor(params) {...}
bar() {...}
}
/* globally accessible factory method */
function createFoo(fooParams) {
return new Foo(fooParams);
}
// Client GAS project
function test() {
var foo = FooService.createFoo(fooParams);
Logger.log(foo.bar());
}

Scala - unbound wildcard exception (Play Framework 2.3 Template)

I am using Play Framework 2.3 I am using the scala template engine to create my views and Java elsewhere.
My model extends an abstract parameterised object like so... (pseudo code)
Abstract object:
public abstract class MyObject<T> {
// various bits
public class MyInnerObject {
// more stuff
}
}
Model object (singleton)
public class SomeModel extends MyObject<SomeBean> {
public static SomeModel getInstance() {
if (instance == null)
instance = new SomeModel();
return instance;
}
// more bits
}
I then pass the model to the view from another view helper:
#MyHelper(SomeModel.getInstance())
MyHelper scala view template:
#*******************************************
* My helper
*******************************************#
#(myObj: some.namespace.MyObject[_])
#import some.namespace.MyObject
#doSomething(myInnerObj: MyObject[_]#MyInnerObject) = {
#* do some stuff *#
}
#for(myInnerObj <- myObj.getInnerObjects()) {
#doSomething(myInnerObj)
}
However I get an error on the line #doSomething(myInnerObj: MyObject[_]#MyInnerObject) stating
unbound wildcard exception
I am not sure the correct Scala syntax to avoid this error I had naively assumed that I could use the _ to specify arbitrary tyope but it won't let me do this.
What is the correct syntax?
UPDATE 1
Changing the method definition to:
#doSomething[T](myInnerObj: MyObject[T]#MyInnerObject)
gives further errors:
no type parameters for method doSomething: (myInnerObj:[T]#MyInnerObject)play.twirl.api.HtmlFormat.Appendable exist so that it can be applied to arguments (myObj.MyInnerObject)
--- because ---
argument expression's type is not compatible with formal parameter type;
found : myObj.MyInnerObject
required: MyObject[?T]#MyInnerObject
It would seem that the Twirl templating engine does not support this syntax currently, although I'm not 100% sure.
I can solve the problem by removing the doSomething method completely...
#*******************************************
* My helper
*******************************************#
#(myObj: some.namespace.MyObject[_])
#import some.namespace.MyObject
#for(myInnerObj <- myObj.getInnerObjects()) {
<div>#myInnerObj.getSomeProperty()</div>
}
But I am bout 10% happy with the solution... It works at least but it feels very restricting that I cannot delegate to methods to help keep my code maintainable. By the look of the comments the problem seems to be a limitation in Twirl, not allowing type arguments for functions in views.
Note: I have accepted this answer as it removes the original problem of the exception however this is only because the solution I want doesn't exist... yet.

In Haxe (JS Target) is there a way to make static members available to another class as if it was its own?

I have this Haxe class that is growing quite large. It consists mostly of static methods & properties. (It's a module set to compile as JS target).
I would like to separate some of the complex static functions into another class.
Is there any way to mark it with a metatag / indicate the other class is an "extension" to the original class?
Something like #:native("OriginalClass") class OtherClass {...}
The goal is to avoid having to write the full variable access (ex: OriginalClass.LOG_QUEUE vs. LOG_QUEUE) or clutter the imports with each OriginalClass's static methods / properties used at the top of the OtherClass. Basically, something to make it aware that it "is" using the same members as the OriginalClass (whenever an 'undefined' one is found, at compile-time).
Example:
If OriginalClass has static var LOG_QUEUE:Array<String>; then OtherClass would be aware that any usage of LOG_QUEUE compiles to this JS code OriginalClass.LOG_QUEUE
Alright, got a solution after discussing with Dima Granetchi from the Haxe experts group on Slack.
Now, although this will still generate the OtherClass that makes use of the OriginalClass's static members, you can cut down on the quantity of import statements for most (if not all) of the module/class's static members by using the wildcard * symbol, like in this example:
// OriginalClass.hx
package somePackage;
class OriginalClass {
public static var LOG_QUEUE:Array<String>;
public static function main() {
LOG_QUEUE = [];
OtherClass.doSomething();
}
public static function doSomethingOriginal() {
LOG_QUEUE.push("World!");
}
}
// OtherClass.hx
import somePackage.OriginalClass.*; // <-- Demonstrating the WILDCARD (*) symbol
class OtherClass {
public static function doSomething() {
LOG_QUEUE.push("Hello"); //Resolved to OriginalClass.LOG_QUEUE
doSomethingOriginal(); //Resolved to OriginalClass.doSomethingOriginal()
}
}
Although this is a minimal example, it becomes more useful when you have a few different dozen static members used in your OtherClass.
Note
TypeDefs defined in the OriginalClass used inside the OtherClass doesn't seem to get recognized/resolved (may be due to missing public accessor, but I was unable to set it on my typedefs). You can always import those specific TypeDefs with individual import statements, like so:
//Somewhere at the top of OtherClass.hx...
import somePackage.OriginalClass.MyTypeDef;

Create coffeescript class

I have simple class in coffeescript (this class is located in file.js.coffee):
class ExampleClass
constructor: (arguments) ->
makeSTH: (page) ->
makeSTHElse: (data) =>
I have another coffee file. I included above file and I tried to create instance of ExampleClass this way:
/#= require file.js.coffee
class ExampleClass2
constructor: (arguments) ->
#ex = new ExampleClass(sth)
But I got something like this:
ReferenceError: ExampleClass is not defined
I don't know how to correctly reference to ExampleClass. Thanks for all answers and sorry for my English.
CoffeeScript will compile each of the source file as a separated compilation unit. Each of the compilation unit will be wrapped inside a block, so that the global namespace won't be polluted by mistake. So, ExampleClass actually get compiled to something like:
(function () {
var ExampleClass;
ExampleClass = function (args) {}
...
}).call(this);
You can see that ExampleClass can only be accessed from the same source. In order to access it from other source file, you need to bind it to window.
class window.ExampleClass
constructor: (args) ->
...
PS. you're not allowed to use arguments as formal parameter name in CoffeeScript, as it has special meaning in JavaScript.
And /#= require file.js.coffee is not valid in CoffeeScript, you need to remove the leading /. I think that's just a typo.

Extending a class in another file

I have some TypeScript code that is being generated by a tool. I'd like to extend this class in another file. As of 0.9.1.1, what's the best way to go about this?
I thought maybe I could staple my additional functions onto the prototype, but this is giving various errors (which change depending what mood the compiler is in).
For example:
Foo.ts (generated by a tool)
module MyModule {
export class Dog { }
}
Bar.ts
module MyModule {
function bark(): string {return 'woof';}
Dog.prototype.bark = bark;
}
You cannot split a class definition between multiple files in TypeScript. However typescript understands how JavaScript works and will let you write idomatic JavaScript classes just fine:
module MyModule {
export function Dog(){};
}
module MyModule {
function bark(): string {return 'woof';}
Dog.prototype.bark = bark;
}
Try it online
One way around this is to use inheritance:
class BigDog extends Dog{
bark(){}
}
I have encountered your problem as well before, but I had some deeper problems. You can see from basarat's example, that simple functions can be added as an extension to the prototype, but when it comes to static functions, or other static values you might want to extend your (presumably third party) class, then the TSC will warn you, that there is no such method defined on the class statically.
My workaround was the following little hack:
module MyModule {
export function Dog(){};
}
// in the other file
if (typeof MyModule !== 'undefined'){
Cast<any>(MyModule.Dog).Create = ()=>{return new Dog();};
}
// where Cast is a hack, for TS to forcefully cast types :)
Cast<T>(element:any):T{ return element; }
This should cast MyModule.Dog, to an any object, therefore allowing attachment of any kinds of properties, functions.