I'm trying to access the DOM element as a JS object.
let navRef = React.useRef(Js.Nullable.null);
let width =
switch (Js.Nullable.toOption(navRef)) {
| None => 0.0
| Some(nav) => ReactDOMRe.domElementToObj(nav)##clientWidth
};
But I have a type eror on navRef inside Js.Nullable.toOption
Error: This expression has type React.Ref.t(Js.Nullable.t('a))
but an expression was expected of type
Js.Nullable.t('b) = Js.nullable('b)
React.Ref.t is an opaque type, hence you can't pattern match on it directly. But you can access the value of the ref using React.Ref.current and then pattern match on that:
let navRef = React.useRef(Js.Nullable.null);
let width =
switch (Js.Nullable.toOption(React.Ref.current(navRef))) {
| None => 0.0
| Some(nav) => ReactDOMRe.domElementToObj(nav)##clientWidth
};
Related
I am reading this tutorial https://www.stackbuilders.com/blog/nonsense-getting-started-with-reason-and-reason-react/. One of the problems I am facing is that api.noopschallenge.com is now dead. I replaced the API call to this https://random-word-api.herokuapp.com/word?number=20 This works but returns a Json Array. I have to convert the Json Array to list(string).
I modified the decodeWords function as
let decodeWord = (json: Js.Json.t) : list(string) =>
switch(Js.Json.decodeArray(json)) {
| None => []
| Some(array) => Belt.Array.map(Js.Json.decodeString, array)
};
But this gives me error
This has type:
Js.Json.t => option(Js.String.t) But somewhere wanted:
array('a)
How do I convert the Json Array to list(string)?
Two problems:
You've switched the arguments to Belt.Array.map around.´array` should come first.
Since decodeString returns an option(string) instead of just a string, you'll have to deal with the Nones somehow. Using Belt.Array.keepMap is a shorter way of just ignoring them.
let decodeWords = (json: Js.Json.t): list(string) =>
switch (Js.Json.decodeArray(json)) {
| None => []
| Some(array) =>
array->Belt.Array.keepMap(Js.Json.decodeString)->Belt.List.fromArray
};
But using the Js.Json API directly is rather cumbersome. You might want to consider using a third-party json decoding library such as bs-json (disclaimer: authored by me) instead. Then it would be as simple as:
let decodeWords = Json.Decode.(list(string))
Or, if you still want it to return an empty list instead of raising an exception on decode failure:
let decodeWords = Json.Decode.(withDefault([], list(string)))
I think I resolved it myself. but if you know of a better solution then please let me know
let decodeWords = (json: Js.Json.t) : list(string) =>
switch(Js.Json.decodeArray(json)) {
| None => []
| Some(array) => Belt.Array.reduce(array, [], (acc, value) => {
switch(Js.Json.decodeString(value)) {
| None => acc
| Some(v) => [v, ...acc]
}
})
};
I am using r2d2_postgres to run raw SQL and return the result directly in Actix response.
I need to run raw sql with dynamic data, types and unknown at compile time columns/data types etc. To do this, I came across serde_json::value::RawValue:
It states: "A RawValue can be used to defer parsing parts of a payload until later, or to avoid parsing it at all in the case that part of the payload just needs to be transferred verbatim into a different output object."
https://docs.serde.rs/serde_json/value/struct.RawValue.html
I basically want to avoid parsing it at all and just send it to the Actix client.
Here's my code:
let mut conn = pool.get().expect("Couldn't get db connection from pool");
let result = web::block(move || conn.query("select jsonb_agg(t) from (select * from useraccountview) t",&[]))
.await;
match result {
Ok(result) => {
let foo : serde_json::value::RawValue = result[0].get(0);
HttpResponse::Ok().content_type("application/json").json(foo)
},
Err(e) => HttpResponse::NotAcceptable().body(e.to_string())
}
This gives me 2 errors:
error[E0277]: the trait bound `serde_json::value::RawValue: FromSql<'_>` is not satisfied
--> src/main.rs:188:63
|
188 | let foo : serde_json::value::RawValue = result[0].get(0);
| ^^^ the trait `FromSql<'_>` is not implemented for `serde_json::value::RawValue`
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> src/main.rs:188:17
|
188 | let foo : serde_json::value::RawValue = result[0].get(0);
| ^^^ doesn't have a size known at compile-time
I am very new to Rust so I am probably missing some concept on how to fix this.
I have this enum
public enum Format {
case label(key: String)
case textField(key: String)
case image(key: String)
}
And I can use it like:
Format.label(key: "abc")
Format.textField(key: "0.0")
Format.image(key: "mystringfile")
When I try to get the value, I can do it with this:
let control = Format.label(key: "abc")
if case let Format.label(key) = control {
tmp = key
} else if case let Format.image(key) = control {
tmp = key
} else if case let Format.textField(key) = control {
tmp = key
}
With that I can get the value, but I'm not finding the case label, textfield or image.
How I can find the enum that belongs that variable?
If I try to use something like this:
control == Format.label
I get the error:
Binary operator '==' cannot be applied to operands of type
'Table.Format' and '(String) -> Format'
I may misunderstand your question but why not use a switch?
let control = Format.label(key: "abc") // or = Format.textField(key: "whatever") or = Format.image(key: "whatever")
let tmp: String
switch control {
case .label(let key):
// It's a label, do what you need
tmp = key
case .textField(let key):
// It's a textField, do what you need
tmp = key
case .image(let key):
// It's a image, do what you need
tmp = key
}
This lets you act on the type and get the value.
Let us consider a simple enum implementation with a static method that check whether a value has an associated value (the efficiency of the implementation is not to be regarded here):
enum Letter {
Alpha = -1,
A = 0,
B = 1,
C = 2,
}
impl Letter {
pub fn in_enum(value: isize) -> bool
{
match value {
-1 => true,
0 => true,
1 => true,
2 => true,
_ => false,
}
}
}
Now, let us write a macro for building enums with an equivalent in_enum method. The macro below was written with some guidance from the Serde guide for enum deserialization as numbers, in which matching for enum variant values also occurs.
macro_rules! my_enum {
($name:ident { $($variant:ident = $value:expr, )* }) => {
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum $name {
$($variant = $value,)*
}
impl $name {
pub fn in_enum(value: isize) -> bool
{
match value {
$( $value => true, )*
_ => false,
}
}
}
}
}
my_enum!(Letter {
Alpha = -1,
A = 0,
B = 1,
C = 2,
});
Playground.
With version 1.18.0, the compiler won't accept the variant with a negative integer.
error: expected pattern, found `-1`
--> src/main.rs:13:24
|
13 | $( $value => true, )*
| ^^^^^^
This seems to happen regardless of how I write this pattern down in the macro, or whether I use i32 or isize for the value method parameter. Changing the fragment specifier of $value to pat is also out of the question: the compiler will refuse to build the enum, even without negative variant values.
error: expected expression, found `-1`
--> src/main.rs:5:26
|
5 | $($variant = $value,)*
| ^^^^^^
What's surprising about this is that it works without using macros, as well as when I discard the Alpha variant.
Why does this happen?
This is a bug in the compiler and is already fixed in the nightly version as of today (Jul 5, 2017), and released in stable version 1.20.0.
Im stuck with with code, whenever I try to run it I get the error:
Error:(37, 66) missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: com.bfg.domain.model.RunnerSnap
def syncPrices(pair: (RunnerSnap, RunnerChange)): RunnerSnap = {
However the error message is not enogh for me to know what I need to change to get this working.
def syncPrices(pair: (RunnerSnap, RunnerChange)): RunnerSnap = {
case (cache: RunnerSnap, delta: RunnerChange) =>
val newHc = if (delta.hc.isEmpty) cache.runnerId.handicap else delta.hc
val id = RunnerId(delta.id, newHc)
val prices = MarketRunnerPrices(
atl = syncPriceVolume(cache.prices.atl, delta.atl),
atb = syncPriceVolume(cache.prices.atb, delta.atb),
trd = syncPriceVolume(cache.prices.trd, delta.trd),
spb = syncPriceVolume(cache.prices.spb, delta.spb),
spl = syncPriceVolume(cache.prices.spl, delta.spl),
batb = syncLevelPriceVolume(cache.prices.batb, delta.batb),
batl = syncLevelPriceVolume(cache.prices.batl, delta.batl),
bdatb = syncLevelPriceVolume(cache.prices.bdatb, delta.bdatb),
bdatl = syncLevelPriceVolume(cache.prices.bdatl, delta.bdatl),
spn = if (delta.spn.isEmpty) cache.prices.spn else delta.spn,
spf = if (delta.hc.isEmpty) cache.prices.spf else delta.spf,
ltp = if (delta.hc.isEmpty) cache.prices.ltp else delta.ltp,
tv = if (delta.hc.isEmpty) cache.prices.tv else delta.tv
)
RunnerSnap(id, prices)
}
My question is: Why am I getting this error and what do I need to
change in my code to get it working as expected?
You are missing pair match:
def syncPrices(pair: (RunnerSnap, RunnerChange)): RunnerSnap = pair match {
case (cache: RunnerSnap, delta: RunnerChange) =>
...
}