How do I declare global variables in Pact lang? - pact-lang

I'm writing a smart contract and I want to declare global variables. I want the functions in my smart contract to be able to access and update these variables.
For example, in Solidity I can do this as follows:
pragma solidity ^0.5.0;
contract SolidityTest {
uint someSmartContractVar; // State variable
constructor() public {
someSmartContractVar = 10; // Setting the variable
}
...
}
I see the coin contract makes use of defconst here:
(defconst COIN_CHARSET CHARSET_LATIN1
"The default coin contract character set")
This approach is good for variables that need to be accessible by the rest of the contract, but I don't think I can change the values of these variables at some later point.
One possibility is creating a table named "global-variables" and storing the specific variables there. So then the functions can access and change these variables via table reads and updates. For example:
(defschema global-variable-schema
someSmartContractVar:decimal)
(deftable global-variables:{global-variable-schema})
(defconst GLOBAL_VAR_KEYNAME "global-vars")
(defun constructor:string ()
(insert global-variables GLOBAL_VAR_KEYNAME
{ 'someSmartContractVar: 10.0 }
)
"Global variables set"
)
(defun get-someSmartContractVar:decimal ()
(at "someSmartContractVar" (read global-variables GLOBAL_VAR_KEYNAME))
)
Is this the recommended approach for this type of use case?

Great question and that solution should work!
I don't know of any other practical way to do it.

Related

Swift Array multiple appending on click

I'm creating a button that when clicked adds the current date and time to an array but when I try to append to the array it only appends once and not repeating the process
the Entries struct:
struct Enteries {
var dates:[String] = []
}
convert date to String:
func DateConverter(){
format.timeZone = .current
format.dateFormat = "yyyy-MM-dd HH:mm"
dateString = format.string(from: currentDate)
}
The function that appends: also its called later whenever an IBAction is triggered
func AddToDatabase () {
var entery = Enteries()
entery.dates.append(dateString)
print(entery.dates)
}
`
Yikes, there's a lot going on here.
First of all, Swift's convention is to use lowerCamelCase for functions. Only type names should be UpperCamelCase.
Secondly, function names should be verbs or verb phrases, type names should be nouns. If I saw DateConverter in some code, I would expect it to be a type. It's an UpperCamelCase noun, that's how types should be named. But yours is a function (which would be a total surprise to every other Swift developer, because it violates the expectations they've built up from Swift's naming conventions), that function should probably be called parseDate.
Which way does DateConverter convert? From String to Date, Date to String, or both? What's its input? What's it's output? These things should be obvious from a good function name, but are totally unknown here without looking at the implementation.
Critically, the DateConverter function doesn't take input from parameters, and doesn't return a result, instead it takes input from a side effect (accessing the variable currentDate) and returns a result via side effect (writing to an a variable dateString). This is really bad, for several reasons:
It's not reusable. You have no way to use this date parsing code somewhere else without copy/pasting it, which is how code duplication and complexity arise. If you ever decide to change the date format in your app, you won't have a central source-of-truth that you can change, instead you'll have to manually hunt down every copy of this function, and change it, hoping you don't miss any. Not good.
It's not thread safe
It's more complex than a simple function that has type (Date) -> String. It obfuscates what's going on.
It defies peoples' expectations, without justification.
Enteries.dates has a default value of [], which doesn't seem to be a good idea if you're going to be appending to it as soon as you create it. Instead, take the array via an initializer parameter.
Enteries.dates has type [String]. Why?! You already have Date objects, store those!
They're smaller (in memory)
They're presentation-agnostic, meaning you can properly format them for different interfaces and different locales at a later time, as necessary
They support date math. I often see people storing dates as strings, and ask questions like "How do I sort my array of dates?" (which are actually stored as strings), "How do I add 1 day to "2019-12-24", and they start doing funky parsing, splitting, joining, and it's all just an absolute mess
Here's how I would improve this code:
struct Entries {
var entries: [Entry]
}
struct Entry {
let date: Date
}
// Call this from your view layer, only when you're about to present a `Date` to a user.
func parse(date: Date) -> String {
let df = DateFormatter()
df.timeZone = .current
df.dateFormat = "yyyy-MM-dd HH:mm"
return format.string(from: currentDate)
}
var entries = Entries(entries: [])
func addToDatabase(entry: Entry) {
entries.append(entry)
print(enteries.entries)
}
you are creating a new entery object eveytime the function is called. SO its creating a new object everytime. Declare your entery object outside the function.
var entery = Enteries()
func AddToDatabase () {
entery.dates.append(dateString)
print(entery.dates)
}

Good practice to hold a file or channel in a class

In the following code, I am trying to make a class which can write something to a log file when asked via a method. Here, I am wondering if this is an idiomatic way for this purpose, or possibly is there a more recommended way, e.g., hold a separate field of file type (for some reason)? In other words, is it pratically no problem even if I hold only a channel type?
class Myclass {
var logfile: channel;
proc init() {
writeln( "creating log.out" );
logfile = openwriter( "log.out" );
}
proc log( x ) {
logfile.writeln( x );
}
}
proc main() {
var a = new borrowed Myclass();
a.log( 10 );
a.log( "orange" );
}
I believe what you're doing here is reasonable. The distinction between files and channels in Chapel is primarily made in support of the language's parallel computing theme, in order to support having multiple tasks access a single logical file simultaneously using distinct channels (views into the file, essentially). In a case like yours, there is a file underlying the channel you've created, but there's no need to explicitly store it if you have no need to interact further with it.
So I believe there is no practical problem to simply storing a channel as you have here.

Swift can't call self from c callback in linphone sdk

I have problem when try to call Swift instance method from c callback.
Error: "A C function pointer cannot be formed from a closure that captures context."
linphone_core_cbs_set_registration_state_changed(cbs) { (lc, cfg, state, message) in
switch state{
case LinphoneRegistrationOk:
print("LinphoneRegistrationOk")
self.call()
}
func call() {
let account = "test"
let domain = "sip.linphone.org"
let identity = "sip:" + account + "#" + domain
linphone_core_invite(lc, identity)
}
If you have the ability to pass an arbitrary void* as a context then using Unmanaged<SelfType>.passUnretained(self).toOpaque() and converting it back with Unmanaged<SelfType>.fromOpaque(context).takeUnretainedValue() is the best solution.
But based on your small snippet of (lc, cfg, state, message) none of them seem like a context pointer. So getting self back is still possible but likely more complex. Because you will need to create a global/static piece of data that can be accessed from inside your closure in a safe manner. Some ideas of how you can do this are below:
1) You can do this with just a simple global/static if you know that is safe.
2) You can use thread local storage and store a pointer to self and cast it back and forth in the same way as if you had the void* argument and used Unmanaged. This one of course requires that your C callback be raised on the same thread where you store the value.
3) If you have access to a unique identifier that both Swift and C can access that will continue to be valid and accessible in your callback you can create a map of type [UniqueIdentifierAccessibleBySwiftAndC: TypeOfSelf] and use that to get self back.

Lua C modules: confused about including members

I am trying to register a Lua C module that I need to use like this.
local harfbuzz = require 'harfbuzz'
-- initialize blob
local blob = harfbuzz.Blob.new(…)
print(blob:length())
My understanding is that I should create a new table and add a metatable to it with the methods, and then add that table as a member Blob to the top-level lib table.
Here is the relevant snippet of code in my C file. I am not very sure what to include in the register_blob function. I tried a few things and they did not work.
static const struct luaL_Reg blob_methods[] = {
{ "length", blob_length },
{"__gc", blob_destroy },
{ NULL, NULL },
};
static const struct luaL_Reg blob_functions[] = {
{ "new", blob_new },
{ NULL, NULL }
};
static const struct luaL_Reg lib_table [] = {
{"version", get_harfbuzz_version},
{NULL, NULL}
};
int register_blob(lua_State *L) {
// QUESTION: What should I include here
}
int luaopen_luaharfbuzz (lua_State *L) {
lua_newtable(L);
register_blob(L);
luaL_setfuncs(L, lib_table, 0);
return 1;
}
What register_blob does really depends on what new_blob needs to do. The two feed into one another.
Given your use case, new_blob needs to create new objects, and those new objects have metatable members equal to your blob_methods table. So, what new_blob needs to do is:
Create a table/userdata to be returned.
Assign that table/userdata a metatable built from the contents of blob_methods table.
Do whatever other initialization work is needed on the object.
Return the object.
So what your register_blob code needs to do is build the metatable that you intend to use in step 2, then store it somewhere that new_blob can easily access it. But also somewhere that noone else can. Or at least, noone outside of C code.
Lua being well designed, it has a place for storing exactly this kind of data. It's called the Lua registry table. The registry acts like a global table. But it can only be access from C; Lua code can't touch it (well, unless you use the debug library. Or pass the registry table to Lua).
The idiomatic way (as I understand it) that the registry is used is that every C module stakes out its own table index in the registry. So your luaopen_luaharfbuzz function would create a table and store that into a key in the registry. The key would probably some string, likely named after your module. And you put all your private stuff into that table.
So your register_blob function would:
Create the table that will be used as the metatable for blob objects.
Use luaL_setfuncs to set the blob_methods into the newly created table.
Get the harfbuzz table from the registry.
Put the newly created table into a known key in the harfbuzz table from the registry.
That way, new_blob knows exactly where to go to get the metatable to use.

Parsing data into a module-level mutable static variable

I have a set of functions within a module that need access to some shared initialization-time state. Effectively I'd like to model this with a static mutable vector like:
static mut defs: Vec<String> = vec![];
fn initialize() {
defs.push("One".to_string());
defs.push("Two".to_string());
}
(Example: http://is.gd/TyNQVv, fails with "mutable statics are not allowed to have destructors".)
My question is similar to Is it possible to use global variables in Rust?, but uses a Vec (i.e. a type with destructor), so the Option-based solution to that question doesn't seem to apply. Namely, this fails with the same error as my first attempt:
static mut defs: Option<Vec<String>> = None;
fn initialize() {
let init_defs = vec![];
init_defs.push("One".to_string());
init_defs.push("Two".to_string());
defs = Some(init_defs);
}
Is there a way to get access to a static ("global") vector that is populated at initialization time and visible at runtime?
Are there other patterns I should be considering to support this use case? Passing explicit references to the state vector is possible, but would clutter up a very large number of function signatures that all need access to this state.
You can use lazy_static for this purpose:
lazy_static! {
static ref defs: Vec<String> = {
let mut init = vec!["One".to_string(), "Two".to_string()];
// init.push(...); etc. etc.
init
}
}
That initialises a vector on the first access, and it is immutable after that. If you wish to modify it later, wrapping it in a std::sync::Mutex is a good first step.
Are there other patterns I should be considering to support this use case? Passing explicit references to the state vector is possible, but would clutter up a very large number of function signatures that all need access to this state.
One pattern to consider is creating a context object that stores all the info the functions need, e.g.
struct Context {
defs: Vec<String>
}
and then passing around Context ensures everyone knows what they need to know. You can even consider putting all/many/some of the functions as methods on Context, e.g.
impl Context {
fn foo(&self) {
if self.defs.len() > 10 {
println!("lots of defs");
}
}
// ...
}
This pattern is especially good if you need to modify the context (automatically ensures thread safety), and/or if you wish to have several independent instances in a single process.

Resources