How Do I Set a Long Integer Property in Gremlin JavaScript? - gremlin

** PROBLEM **
I need to set a long integer value in a vertex from my JavaScript/TypeScript code.
** WHY IS THIS AN ISSUE? **
JavaScript stores number as a double in Java or C# world as we can see in the following example:
public static async experiment(): Promise<any> {
const g = GremlinDb.g;
await g.addV("test")
.property("number", 3).iterate();
return {};
}

Use toLong() in exports.toLong in gremlin-javascript/src/main/javascript/gremlin-javascript/lib/utils.js
public static async experiment(): Promise<any> {
const g = GremlinDb.g;
await g.addV("test")
.property("number", toLong(3)).iterate();
return {};
}

Related

The return type of an async method must be void

I am currently following a course on how to build a ASP.NET blazor app and have reached a dead end. As the title states, the method CreateMauiApp() requires a void return type. One critical difference is that I am following a course that is 1 year old and does not cover Maui which I am using. Is there any work-around to this issue that anyone knows of?
public static class MauiProgram
{
public static async MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.RegisterBlazorMauiWebView()
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
});
//builder.Services.AddSingleton<IUserManager, UserManager>();
//builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddSingleton<IUserManager, UserManagerFake>();
builder.Services.AddScoped<ICurrentUserService, CurrentUserService>();
builder.Services.AddBlazorWebView();
var host = builder.Build();
var currentUserService = host.Services.GetRequiredService<ICurrentUserService>();
TestData.CreateTestUser();
currentUserService.CurrentUser = TestData.TestUser;
await host.RunAsync();
}
}
}
Error messages:
Error CS0161 'MauiProgram.CreateMauiApp()': not all code paths return a value UdemyCourseIntro (net6.0-android), UdemyCourseIntro (net6.0-ios), UdemyCourseIntro (net6.0-maccatalyst), UdemyCourseIntro (net6.0-windows10.0.19041) C:\Users\matej\source\repos\UdemyCourseIntro\UdemyCourseIntro\MauiProgram.cs 11 Active
Error CS1983 The return type of an async method must be void, Task, Task, a task-like type, IAsyncEnumerable, or IAsyncEnumerator UdemyCourseIntro (net6.0-android), UdemyCourseIntro (net6.0-ios), UdemyCourseIntro (net6.0-maccatalyst), UdemyCourseIntro (net6.0-windows10.0.19041) C:\Users\matej\source\repos\UdemyCourseIntro\UdemyCourseIntro\MauiProgram.cs 11 Active
So the issue was exactly as someone politely stated in one of the comments. All I had to do is delete the async and return a MauiApp object.
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.RegisterBlazorMauiWebView()
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
});
//builder.Services.AddSingleton<IUserManager, UserManager>();
builder.Services.AddSingleton<IUserManager, UserManagerFake>();
builder.Services.AddScoped<ICurrentUserService, CurrentUserService>();
builder.Services.AddBlazorWebView();
//builder.Services.AddSingleton<WeatherForecastService>();
var host = builder.Build();
var currentUserService = host.Services.GetRequiredService<ICurrentUserService>();
TestData.CreateTestUser();
currentUserService.CurrentUser = TestData.TestUser;
host.RunAsync();
return host;
}
}
}

Flutter/Firestore- Retrieving product information issue

I am trying to load all of my product data from firestore. I have a data schema:
class SingleProduct with ChangeNotifier {
static const EVENT = "event";
static const IMGURL = "imgUrl";
static const NAME = "name";
static const PRICE = "price";
//Private Variables
String _event;
String _imgUrl;
String _name;
double _price;
// getters
String get event => _event;
String get imgUrl => _imgUrl;
String get name => _name;
double get price => _price;
SingleProduct.fromSnapshot(DocumentSnapshot snapshot) {
_event = snapshot.data()[EVENT];
_imgUrl = snapshot.data()[IMGURL];
_name = snapshot.data()[NAME];
_price = snapshot.data()[PRICE];}
}
I have then created a class to map all the data received to a list of products:
class ProductServices {
FirebaseFirestore _firestore = FirebaseFirestore.instance;
String collection = 'products';
Future<List<SingleProduct>> getAllProducts() async =>
_firestore.collection(collection).get().then((snap) {
print(snap.docs.length); // returns 11 products as expected
List<SingleProduct> allProducts = [];
snap.docs.map((snapshot) =>
allProducts.add(SingleProduct.fromSnapshot(snapshot)));
print(allProducts.length); //returns 0 so I think my map isn't working
return allProducts;
});
}
The Firestore query returns 11 query snapshots as expected but I then try and add them to a list using my product schema but the the results show the list has 0 elements. Any suggestions how to map the results of my fire base query to a list?
Use forEach():
snap.docs.forEach((snapshot) => allProducts.add(SingleProduct.fromSnapshot(snapshot)));
Explanation time: [tl;dr Your lambda wasn't executed at all]
map() is a lazy function intended for transforming elements in a list, which works only if the result is going to be used.
In your code, the result of map() is nowhere used later (eg. assigned to a variable), which is why the lambda within it is not called (why would it transform if the transformation is not used ahead?)
Also, it's not apt for your use-case.
To demonstrate its laziness, try running this code in DartPad:
void main() {
List<String> list = ["a", "b", "c"];
List<String> anotherList = [];
var mappingOutput = list.map((element) { anotherList.add(element); return element + "X"; }).toList();
print(list);
print(mappingOutput);
print(anotherList);
}
Notice that the result of map() is to be given back to a variable mandatorily, which pushes the laziness aside and executes it.
anotherList will be filled.

Wrong order of execution in Flutter asynchronous code

I am having problems with futures in a Flutter app.
void saveCats() async {
var cats = await convertToCats(_rawData);
await DatabaseProvider.db.addCats(cats);
}
Future<List<Cat>> convertToCats(CatList catData) async {
var cats = <Cat>[];
await catData.forEach(key, value) async {
var pos = await calculatePos();
print('This should come first');
cats.add(Cat(name: key, pos: pos);
}
}
Future<int> calculatePos() async {
return await DatabaseProvider.db.calculatePos();
}
database.dart:
Future<void> addCats(List<Cat> cats) async {
print('This should come second');
// Do adding stuff here
}
Future<int> calculatePos() async {
// Some code to calculate the position
return pos;
}
In the above code, the saveCats function is called when a button is tapped. This function converts some raw data to a list of Cat models, and adds them to the database. As part of this conversion process, it calculates the pos of the cat in a list. My problem is that I would expect that, of my two print statements, the one in the forEach loop should come before the one in the addCats database function. But instead they appear in reverse order. Where am I going wrong?
You can't async/await in List.forEach() or Map.forEach() as both of them return void.
Either use
await Future.forEach([1, 2, 3], (num) async {
await asyncMethod(num);
});
or something similar;
https://api.flutter.dev/flutter/dart-async/Future/forEach.html
forEach often doesn't do what you expect, because the provided function runs as a closure.
It's more natural when you want to iterate over a list doing something to each element to use for (or one of the more functional type methods like map).
It's not clear what type CatList is, so this is approximate, but you'll want something more like:
Future<List<Cat>> convertToCats(CatList catData) async {
var cats = <Cat>[];
for (var i = 0; i < catData.length; i++) {
var key = catData[i].key;
var pos = await calculatePos();
print('This should come first');
cats.add(Cat(name: key, pos: pos));
}
return cats;
}
or
Future<List<Cat>> convertToCats(CatList catData) async {
return catData.map(...some mapping function...).toList();
}

Using ES6 Map with Flow type

I'm trying to wrap my head around flow and I struggle to make it work with ES6's Map
Consider this simple case (live demo):
// create a new map
const m = new Map();
m.set('value', 5);
console.log(m.get('value') * 5)
flow throws:
console.log(m.get('value') * 5)
^ Cannot perform arithmetic operation because undefined [1] is not a number.
References:
[LIB] static/v0.72.0/flowlib/core.js:532: get(key: K): V | void;
^ [1]
I also tried:
const m:Map<string, number> = new Map();
m.set('value', 5);
console.log(m.get('value') * 5)
But I got the same error
I believe this is because flow thinks that the value can also be something else than a number, so I tried to wrap the map with a strict setter and getter (live demo):
type MyMapType = {
set: (key: string, value: number) => MyMapType,
get: (key: string) => number
};
function MyMap() : MyMapType {
const map = new Map();
return {
set (key: string, value: number) {
map.set(key, value);
return this;
},
get (key: string) {
return map.get(key);
}
}
}
const m = MyMap();
m.set('value', 5);
const n = m.get('value');
console.log(n * 2);
but then I got:
get (key: string) {
^ Cannot return object literal because undefined [1] is incompatible
with number [2] in the return value of property `get`.
References:
[LIB] static/v0.72.0/flowlib/core.js:532: get(key: K): V | void;
^ [1]
get: (key: string) => number ^ [2]
How can I tell flow that I only deal with a Map of numbers?
Edit:
Typescript approach makes more senses to me, it throws on set instead on get.
// TypeScript
const m:Map<string, number> = new Map();
m.set('value', 'no-number'); // << throws on set, not on get
console.log(m.get('value') * 2);
Is there a way to make Flow behave the same way?
What Flow is trying to tell you is that by calling map.get(key), .get(...) may (V) or may not (void) return something out of that map. If the key is not found in the map, then the call to .get(...) will return undefined. To get around this, you need to handle the case where something is returned undefined. Here's a few ways to do it:
(Try)
const m = new Map();
m.set('value', 5);
// Throw if a value is not found
const getOrThrow = (map, key) => {
const val = map.get(key)
if (val == null) {
throw new Error("Uh-oh, key not found")
}
return val
}
// Return a default value if the key is not found
const getOrDefault = (map, key, defaultValue) => {
const val = map.get(key)
return val == null ? defaultValue : val
}
console.log(getOrThrow(m, 'value') * 5)
console.log(getOrDefault(m, 'value', 1) * 5)
The reason that map.get(key) is typed as V | void is the map might not contain a value at that key. If it doesn't have a value at the key, then you'll throw a runtime error. The Flow developers decided they would rather force the developer (you and me) to think about the problem while we're writing the code then find out at runtime.
Random and pretty late, but was searching and came up with this for my own use cases when I didn't see it mentioned:
const specialIdMap = new Map<SpecialId, Set<SpecialId>>();
const set : Set<SpecialId> = specialIdMap.get(uniqueSpecialId) || new Set();
and this saves quite a lot of boilerplate of checking if null and/or whatever. Of course, this only works if you also do not rely on a falsy value. Alternatively, you could use the new ?? operator.

How do I fix this "Constructor cannot be called on object type" error in flow?

I'm having trouble figuring out the problem that flow is complaining about. I'm trying to allow the implementation of an API be changeable by storing the implementation class, then later instantiating it, however, flow complains when I call new this.implKlass saying that "Constructor cannot be called on object type". What is flow trying to tell me, and what am I conceptually missing about how flow works?
Example code below, and flow try code here
/* #flow */
type ApiT = {
fnA(): Promise<*>;
}
// An implementation of the API
class Impl {
async fnA(): Promise<*> { return 1; }
}
class DoThings {
implKlass: ApiT;
constructor(klass) {
this.implKlass = klass;
}
callA() {
const Klass = this.implKlass;
const inst = new Klass();
return inst.fnA();
}
}
new DoThings(Impl).callA();
Example output:
18: const inst = new Klass();
^ constructor call. Constructor cannot be called on
18: const inst = new Klass();
^ object type
13: constructor(klass: ApiT) {
^ property `fnA`. Property not found in
23: new DoThings(Impl).callA();
^ statics of Impl
With a small modification this works.
class DoThings {
implKlass: Class<ApiT>;
constructor(klass) {
this.implKlass = klass;
}
callA() {
const Klass = this.implKlass;
const inst = new Klass();
return inst.fnA();
}
}
The bug was you were writing ApiT instead of Class<ApiT>. ApiT would be an instance of a class, while Class<ApiT> is the class itself.
Try flow link
ApiT describes an object type, not a class type. An instance of the Impl class satisfies the ApiT type, but the class Impl itself does not. You cannot call Impl.fnA(), for example.
I'm not sure if there is any way to pass around constructors like this. However you can accomplish basically the same thing by using a factory function:
type ApiT = {
fnA(): Promise<*>;
}
type ApiTFactory = () => ApiT;
class Impl {
async fnA(): Promise<*> { return 1; }
}
class DoThings {
factory: ApiTFactory;
constructor(factory: ApiTFactory) {
this.factory = factory;
}
callA() {
const factory = this.factory;
const inst = factory();
return inst.fnA();
}
}
new DoThings(() => new Impl()).callA();
tryflow link

Resources