Near-sdk-as Contracts - Singleton style vs Bag of functions - nearprotocol

It seems like there are two styles for writing NEAR smart contracts in assembly script
Bag of functions like Meme Museum
Singleton style like Lottery.
I was wondering under what circumstance one style is recommended over the other.
When should you use one over the other? What are the advantages/disadvantages of each style?

The big differences is in initialization of the contract.
Bag of Functions (BoF)
For the first style, usually a persistent collection is declared at the top level. All top level code in each file is placed into a function and one start function calls each. The Wasm binary format allows to specify the start function so that anytime the binary is instantiated (e.i. loaded by a runtime) that function is called before any exported functions can be called.
For persistent collections this means allocating the objects, but no data is required from storage, until something is read, including the length or size of the collection.
Singleton
A top level instance of the contract is declared. Then storage is checked for the "STATE" key, which contains the state of the instance. If it is present storage is read and the instance is deserialized from storage. Then each "method" of the contract is an exported function that uses the global instance, e.g. instance.method(...), passing the arguments to the method. If the method is decorated with #mutateState then the instance is written back to storage after the method call.
Which To Use
Singleton's provide a nice interface for the contract and is generally easier to understand. However, since you are reading from storage at every method call, it can be more expensive.
The other advantage of the BoF is it's easier to extend as you can export more functions from a dependency.
However, it's also possible to use a combination of both as well.
So really it's whatever makes sense to you.

Related

Dynamic dispatch implementation- virtual function table offset

I'm currently in the code generation phase of building a compiler for a Java-like language. I'm trying to understand how to implement dynamic dispatch for virtual methods.
I get how to build a virtual function table for every class and store a pointer to it in every object. What I don't get is- when generating code for a function call, how do you know what the offset is for that function in the table?
Thanks.
How do you know what anything is in your language? You write it down somewhere while parsing.
What I did in one of my toy languages was to keep a "vtable size" for each class, and when you add a new method to a class, you write down the vtable size as the offset of the method somewhere (i.e. you create a lookup table that maps method name to info about it, like its parameter types and its offset in the vtable), then add to the size to account for the newly-added method.
Of course, this assumes your language actually uses a vtable, like for example C++. If you use messaging in the style of Smalltalk or Objective-C, this table that you build actually gets saved to your compiled product and just used directly. Now a table look-up is slower than just accessing an offset directly, but also has the advantage that a caller does not need to know the type of an object to call a method on it, and you can easily add methods to objects without having to recompile the entire program.

Why use initWith.. methods as opposed to "class/factory methods" in Objective-C?

I've been coding in Objective-C for a few months now and I've noticed that sometimes a class is instantiated (as recommended by documentation) with an init method. Therefore, one must alloc first, and then init. [[Example Class Alloc] initWithProperty1:andTwo:]. However, sometimes the doc recommends using "factory methods" as constructors. Such as [NSArray arrayWithObjects:__].
It seems that with a factory/class method you get the allocation done behind the scenes and the actual method is indistinguishable from the init, AFAIK.
Therefore, what is the practical reason to prefer one over the other? Is my analysis of the two being nearly identical even correct?
I recommend using factory method if there is one that does what you need. Aside from the syntactic sugar (shorter), there are also differences in the object's ownership (and hence who should free it). You shouldn't worry so much about memory if you use ARC.
From Apple's documentation:
Factory methods can be more than a simple convenience. They can not
only combine allocation and initialization, but the allocation can
inform the initialization. As an example, let’s say you must
initialize a collection object from a property-list file that encodes
any number of elements for the collection (NSString objects, NSData
objects, NSNumber objects, and so on). Before the factory method can
know how much memory to allocate for the collection, it must read the
file and parse the property list to determine how many elements there
are and what object type these elements are.
That is a little mystic but consider a use case like this: you want to populate an NSMutableArray with the content of a file. If you choose "alloc and init", the OS must constantly allocate new memory to store the additional data as you read them from the file. The class method needs to parse the file first, so it know how many lines there are and how big of a memory it should ask for in one go.

Wrapping instance variables in accessor methods

Sandy Metz says (POODR book, page 26):
Because it is possible to wrap every instance variable in a method and to therefore treat any variable as if it's just another object, the distinction between data and a regular object begins to disappear.
I am not sure if I understand what she is explaining. When we define the accessors, we are wrapping the instance variables (data) on a method but methods are not objects. So what does she mean when she says that we can treat variables as if they're just another object?
The primary difference between data and objects is behaviour. Objects can modify their internal state without changing their interfaces, while data are static structures.
When we wrap data access within a method, we get the same benefits of an object - the interface remains static to consumers even if the underlying data structure needs to change.

Why create accessor methods when I can just use KVC?

I am trying to get my head wrapped around "key-value coding".
Apple's docs say:
This document describes the NSKeyValueCoding informal protocol, which
defines a mechanism allowing applications to access the properties of
an object indirectly by name (or key), rather than directly through
invocation of an accessor method or as instance variables.
Few thing are confusing me
Accessor methods are automatically generated for properties, and provide several benefits like memory management, custom validations, etc. When we access a property without the accessor methods as the Apple doc says, does that mean we are losing the benefits of accessor methods?
If KVC is so good and it reduces code, why should I use accessor methods, or why are accessor methods still around?
I have never seen in any tutorial or books, or code on GitHub using KVC. Why is it not adopted that widely?
No, it just means that you aren't explicitly calling the accessor in your code. The accessor is called for you by the KVC implementation.
KVC doesn't necessarily reduce code, rather it allows a different way of interacting. It allows more runtime flexibility and it can allow the use of key paths. You shouldn't look at it as a full replacement, just as an alternative which is appropriate in some cases.
It is used widely, you need to look for calls to valueForKey:, setValue:forKey: (the methods of the protocol - there are many more than just these couple).

Ruby: marshal and unmarshal a variable, not an instance

OK, Ruby gurus, this is a hard one to describe in the title, so bear with me for this explanation:
I'm looking to pass a string that represents a variable: not an instance, not the collection of properties that make up an object, but the actual variable: the handle to the object.
The reason for this is that I am dealing with resources that can be located on the filesystem, on the network, or in-memory. I want to create URI handler that can handle each of these in a consistent manner, so I can have schemes like eg.
file://
http://
ftp://
inmemory://
you get the idea. It's the last one that I'm trying to figure out: is there some way to get a string representation of a reference to an object in Ruby, and then use that string to create a new reference? I'm truly interested in marshalling the reference, not the object. Ideally there would be something like taking Object#object_id, which is easy enough to get, and using it to create a new variable elsewhere that refers to the same object. I'm aware that this could be really fragile and so is an unusual use case: it only works within one Ruby process for as long as there is an existing variable to keep the object from being garbage collected, but those are both true for the inmemory scheme I'm developing.
The only alternatives I can think of are:
marshal the whole object and cram it into the URI, but that won't work because the data in the object is an image buffer - very large
Create a global or singleton purgatory area to store a variable for retrieval later using e.g. a hash of object_id:variable pairs. This is a bit smelly, but would work.
Any other thoughts, StackOverflowers?
There's ObjectSpace._id2ref :
f = Foo.new #=> #<Foo:0x10036c9b8>
f.object_id #=> 2149278940
ObjectSpace._id2ref(2149278940) #=> #<Foo:0x10036c9b8>
In addition to the caveats about garbage collection ObjectSpace carries a large performance penalty in jruby (so much so that it's disabled by default)
Variables aren't objects in Ruby. You not only cannot marshal/unmarshal them, you can't do anything with them. You can only do something with objects, which variables aren't.
(It would be really nice if they were objects, though!)
You could look into MagLev which is an alternative Ruby implementation built on top of VMware's Gemstone. It has a distributes object model wiht might suit your use-case.
Objects are saved in the central Gemstne instance (with some nifty caching) and can be accessed by any number of remote worker instances. That way, any of the workers act on the same object space and can access the very same objects simultaneously. That way, you can even do things like having the global Garbage Collector running on a single Ruby instance or seamlessly moving execution at any point to different nodes (while preserving all the stack frames) using Continuations.

Resources