Rescript open is not bringing functions into scope - module

How is open and module prefixing supposed to work in rescript and rescript-react. It doesn't appear to be adhering to the documentation. For example, I have a file reader module
FileReader.res
module FileReader = {
type fileReader
type file = {"name": string, "lastModified": int, "size": int, "type__": string}
#new external createFileReader: unit => fileReader = "FileReader"
#bs.send
external readAsDataURL: (fileReader, file) => unit = "readAsDataURL"
let onload: (fileReader, string => unit) => unit = %raw(`
function (reader, cb) {
reader.onload = function (e) {
cb(e.target.result);
}
}
`)
let fileToDataUrl: (file, string => unit) => unit = (file, continue) => {
let reader = createFileReader()
onload(reader, continue)
readAsDataURL(reader, file)
}
}
That I am trying to use from a react component:
Upload.res
open FileReader
let k = x => (_ => x)
let setState = stateHook => (newVal => stateHook(_ => newVal))
let firstFileFromEvent = event => ReactEvent.Form.target(event)["files"][0]
#react.component
let make = () => {
let (dataUrl, setDataUrl) = React.useState(k(""))
let setDataUrlState = setState(setDataUrl)
let fileOnChange = (event) =>
event ->
firstFileFromEvent ->
FileReader.fileToDataUrl(setDataUrlState)
<div>
<input type_="file" onChange=fileOnChange/>
<img src=dataUrl/>
</div>
}
The only way to get the code to compile is to
open
reference with the module name
my understanding is that you only need to do one or the other. If I remove the open statement, this is the output of the compiler
We've found a bug for you!
src/Upload.res:15:13-36
13 ┆ event -> 14 ┆ firstFileFromEvent -> 15 ┆
FileReader.fileToDataUrl(setDataUrlState) 16 ┆ 17 ┆
The value fileToDataUrl can't be found in FileReader
Adding the open statement back and changing the statement FileReader.fileToDataUrl(setDataUrlState) to fileToDataUrl(setDataUrlState) results in this exception:
We've found a bug for you!
src/Upload.res:15:13-25
13 ┆ event -> 14 ┆ firstFileFromEvent -> 15 ┆
fileToDataUrl(setDataUrlState) 16 ┆ 17 ┆
The value fileToDataUrl can't be found
The source i posted with both the open statement and the module prefix to the function call, compiles but has a warning:
Warning number 44
src/Upload.res:1:1-15
1 │ open FileReader 2 │ 3 │ let k = x => (_ => x)
this open statement shadows the module identifier FileReader (which
is later used)
I am on a mac; using rescript 9.1.4;

In rescript, every code file is itself a module. By putting your code into FileReader.res you've already created a module called FileReader. And by using module FileReader = { ... } you're creating another submodule called FileReader inside it.
The simple solution would then be to just not wrap it in a submodule. Alternatively, you could also open FileReader.FileReader.
What the warning is telling you is that when you open FileReader, you're importing another module called FileReader which shadows (i.e. hides) the top-level module that's also called FileReader.

Related

git-rs leaving index in odd state

I'm using libgit2 via git-rs. I'm trying to commit things which is working, however, old files are showing up as deleted and/or staged even after the commit. How can I clean this up?
let repo: Repository = ...
let head_commit = match repo.head() {
Ok(head) => head.peel_to_commit().ok(),
Err(_) => None,
};
let head_tree = match head_commit {
Some(ref commit) => commit.tree().ok(),
None => None,
};
let mut diff_options = DiffOptions::new();
diff_options
.include_untracked(true)
.recurse_untracked_dirs(true);
let diff_result = self
.repo
.diff_tree_to_workdir_with_index(head_tree.as_ref(), Some(&mut diff_options));
let diff_deltas: Vec<_> = match diff_result {
Ok(ref diff) => diff.deltas().collect(),
Err(_) => Vec::new(),
};
if diff_deltas.is_empty() {
info!("no files changed");
return Ok(());
}
let mut index = .repo.index()?;
for diff_delta in diff_deltas {
let delta = diff_delta.status();
match delta {
Delta::Added
| Delta::Copied
| Delta::Modified
| Delta::Renamed
| Delta::Untracked
| Delta::Unmodified => {
let path = diff_delta.new_file().path().unwrap();
debug!("Staging {:?} file: {:?}", delta, path);
index.add_path(path)?;
}
Delta::Deleted => {
let path = diff_delta.old_file().path().unwrap();
debug!("Unstaging {:?} file: {:?}", delta, path);
index.remove_path(path)?;
}
_ => debug!("skipping {:?} file", delta),
}
}
let index_oid = index.write_tree()?;
let index_tree = self.repo.find_tree(index_oid)?;
let sig = Signature::new(&self.committer.name, &self.committer.email, &time)?;
let parents: Vec<_> = [&head_commit].iter().flat_map(|c| c.as_ref()).collect();
repo.commit(Some("HEAD"), &sig, &sig, message, &index_tree, &parents)?;
index.clear().unwrap();
As #user2722968 pointed out, you must call both index.write() and index.write_tree().
index.write_tree() will create a tree (or trees) from the index, returning the root tree object. This can be used to create a commit.
The trouble here is that you have updated HEAD with the commit that you've created. When you run git status, then that will compare the working directory to the index to the HEAD commit.
In this case, you have made changes to the index, you've updated the index in memory and used that to update HEAD. But you haven't actually written the index itself to disk, so you will see that the working directory does not match the index for any modified files, nor does the index match HEAD. (The working directory and HEAD contents will match, though that is never actually tested by git.)
Once you call index.write() then the working directory, the index and the HEAD commit will all be identical, and thus you'll see the expected (empty) status.

How to write short local open in ReScript?

This compiles in ReasonML:
let testFn = who => Js.(log("Hello " ++ who ++ "!"));
but not in ReScript:
FAILED: src/test.ast
Syntax error!
/xxx/src/test.res:1:25-27
1 │ let testFn = who => Js.(log("Hello " ++ who ++ "!"));
2 │
I'm not sure what to parse here when looking at "(".
Syntax error!
/xxx/src/test.res:1:25-27
1 │ let testFn = who => Js.(log("Hello " ++ who ++ "!"));
2 │
consecutive statements on a line must be separated by ';' or a newline
I didn't find any mention of removal in official docs. Did I miss it? Has syntax changed, or was it removed and not mentioned in docs?
As pointed out by #Yawar in the comments, this short-hand is not supported at time of writing, but is likely to be at some point in the future (see https://github.com/rescript-lang/syntax/issues/2 for discussion).
And just to save a click for those coming across this, a workaround is to rewrite it using a local scope and opening the module in that scope:
let testFn = who => {
open Js
log("Hello " ++ who ++ "!")
}

Workaround for `count.index` in Terraform Module

I need a workaround for using count.index inside a module block for some input variables. I have a habit of over-complicating problems, so maybe there's a much easier solution.
File/Folder Structure:
modules/
main.tf
ignition/
main.tf
modules/
files/
main.tf
template_files/
main.tf
End Goal: Create an Ignition file for each instance I'm deploying. Each Ignition file has instance-specific info like hostname, IP address, etc.
All of this code works if I use a static value or a variable without cound.index. I need help coming up with a workaround for the address, gateway, and hostname variables specifically. If I need to process the count.index inside one of the child modules, that's totally fine. I can't seem to wrap my brain around that though. I've tried null_data_source and null_resource blocks from the child modules to achieve that, but so far no luck.
Variables:
workers = {
Lab1 = {
"lab1k8sc8r001" = "192.168.17.100/24"
}
Lab2 = {
"lab2k8sc8r001" = "192.168.18.100/24"
}
}
gateway = {
Lab1 = [
"192.168.17.1",
]
Lab2 = [
"192.168.18.1",
]
}
From modules/main.tf, I'm calling the ignition module:
module "ignition_workers" {
source = "./modules/ignition"
virtual_machines = var.workers[terraform.workspace]
ssh_public_keys = var.ssh_public_keys
files = [
"files_90-disable-auto-updates.yaml",
"files_90-disable-console-logs.yaml",
]
template_files = {
"files_eth0.nmconnection.yaml" = {
interface-name = "eth0",
address = element(values(var.workers[terraform.workspace]), count.index),
gateway = element(var.gateway, count.index % length(var.gateway)),
dns = join(";", var.dns_servers),
dns-search = var.domain,
}
"files_etc_hostname.yaml" = {
hostname = element(keys(var.workers[terraform.workspace]), count.index),
}
"files_chronyd.yaml" = {
ntp_server = var.ntp_server,
}
}
}
From modules/ignition/main.tf I take the files and template_files variables to build the Ignition config:
module "ingition_file_snippets" {
source = "./modules/files"
files = var.files
}
module "ingition_template_file_snippets" {
source = "./modules/template_files"
template_files = var.template_files
}
data "ct_config" "fedora-coreos-config" {
count = length(var.virtual_machines)
content = templatefile("${path.module}/assets/files_ssh_authorized_keys.yaml", {
ssh_public_keys = var.ssh_public_keys
})
pretty_print = true
snippets = setunion(values(module.ingition_file_snippets.files), values(module.ingition_template_file_snippets.files))
}
I am not quite sure what you are trying to achieve so I can not give any detailed examples.
But modules in terraform do not support count or for_each yet. So you can also not use count.index.
You might want to change your module to take lists/maps of input and create those lists/maps via for-expressions by transforming them from some input variables.
You can combine for with if to create a filtered subset of your source list/map. Like in:
[for s in var.list : upper(s) if s != ""]
I hope this helps you work around the missing count support.

How to save List<Point> into preferences and get List<Point> from preferences in flutter?

Error while using json_serializable
json_serializable:json_serializable on .../sign_point_model.dart:
Error running JsonSerializableGenerator
Could not generate fromJson code for valList because of type Point<num>.
None of the provided TypeHelper instances support the defined type.
json_serializable doesn't know how to convert a Point into JSON. Since you know it's just a pair of nums you could easily convert the list yourself.
import 'dart:convert';
void main() async {
var points = [
Point(Offset(123, 456), PointType.tap),
Point(Offset(3.14159, 3.16227), PointType.move),
];
var simplified =
points.map((e) => [e.offset.dx, e.offset.dy, e.type.index]).toList();
String j = json.encode(simplified);
print(j);
var decoded = json.decode(j) as List;
var asPoints = decoded
.map((e) => Point(Offset(e[0], e[1]), PointType.values[e[2]]))
.toList();
print(asPoints);
}

Dart file read to var

I have looked all over can not find how to read input from file into variables.
trying to do this
in c++
ifstream myFile;
myFile.open("filename.txt");
while(!file.eof()){
myFile >> var1 >> var2 >> etc...
following dart documentation ive got the file open and all but i cannot find examples likes this. would appreciate help and also links to relevant Dart examples , nothing web/app related. just trying to read from a file and do some computation with the stuff thats in the file.
(file has grades and im computing avgs).
sample input.txt file (d123 some student unique id, the numbers are grades).
d123 90 89 60 77 65 100
d124 70 79 88 75 57 89
thanks
You can find the below sample snippet. As I am not sure how big is the file, I am using async and stream API to process line by line. However, if your input is not so big, you can just read entire file at once, and perform the same step. Here are some links with good documentation dart:io, dart:convert
import 'dart:io';
import 'dart:convert';
import 'dart:async';
main(List<String> arguments) {
final file = new File('input/input.txt');
Stream<List<int>> inputStream = file.openRead();
inputStream.transform(UTF8.decoder).transform(new LineSplitter()).listen(
(String line) {
// calculate average score
List<String> list = line.split(" ");
var studentId = list[0];
var averageScore = list
.sublist(1)
.map((value) => int.parse(value))
.reduce((a, b) => a + b) / (list.length - 1);
print('${studentId} has average score of ${averageScore}');
}, onDone: () {
print('File is succeessfully read.');
}, onError: (e) {
print(e.toString());
});
}
I would just read the entire file, split into lines, and then assign variables from there:
import "dart:io";
main() {
var file = new File('input/input.txt');
var lines = file.readAsLinesSync();
var var1 = lines[0];
var var2 = lines[1];
...
}
If it's really important to read only part of the file, then you can use the solution above.