I tried to catch an Exception but the compiler gives warning: This type test or downcast will always hold
let testFail () =
try
printfn "Ready for failing..."
failwith "Fails"
with
| :? System.ArgumentException -> ()
| :? System.Exception -> ()
The question is: how to I do it without the warning? (I believe there must be a way to do this, otherwise there should be no warning)
Like C#
try
{
Console.WriteLine("Ready for failing...");
throw new Exception("Fails");
}
catch (Exception)
{
}
C#:
void testFail()
{
try
{
Console.WriteLine("Ready for failing...");
throw new Exception("Fails");
}
catch (ArgumentException)
{
}
catch
{
}
}
F# equivalent:
let testFail () =
try
printfn "Ready for failing..."
failwith "Fails"
with
| :? System.ArgumentException -> ()
| _ -> ()
C#:
void testFail()
{
try
{
Console.WriteLine("Ready for failing...");
throw new Exception("Fails");
}
catch (ArgumentException ex)
{
}
catch (Exception ex)
{
}
}
F# equivalent:
let testFail () =
try
printfn "Ready for failing..."
failwith "Fails"
with
| :? System.ArgumentException as ex -> ()
| ex -> ()
C#:
void testFail()
{
try
{
Console.WriteLine("Ready for failing...");
throw new Exception("Fails");
}
catch
{
}
}
F# equivalent:
let testFail () =
try
printfn "Ready for failing..."
failwith "Fails"
with
| _ -> ()
As Joel noted, you would not want to use catch (Exception) in C# for the same reason you don't use | :? System.Exception -> in F#.
try
.. code ..
with
| _ as e ->
Related
How i can make a custom encode/decode for CHAR type using GSON library with Kotlin?
My current code don't work and it don't stop on debug.
Appear that type don't match.
My code:
data class Test(
var typeChar: Char,
)
private fun createGson(): Gson {
val builder = GsonBuilder()
// char
builder.registerTypeAdapter(
Char::class.java,
JsonDeserializer<Any?> { json, _, _ ->
try {
Char(json.asJsonPrimitive.asInt)
} catch (e: Exception) {
// ignore
}
null
},
)
builder.registerTypeAdapter(
Char::class.java,
com.google.gson.JsonSerializer<Char?> { value, _, _ ->
JsonPrimitive(value.code)
},
)
return builder.create()
}
Can anyone help me?
I tried a sample code above and search on github gson repository for infos.
The problem is that there are two different types representing characters in Java, char, the primitive type, and Character, the wrapper. The Kotlin type Char can be mapped to either, depending on whether the field is nullable or not. As a result, you have to map both types. This is also mentioned by docs for the registerTypeAdapter method,
This registers the type specified and no other types: you must manually register related types! For example, applications registering boolean.class should also register Boolean.class.
In your case, this means that you need to register your serializer and deserializer for both Char::class.java and Character::class.java:
private fun createGson(): Gson {
val builder = GsonBuilder()
builder.registerTypeAdapter(
Char::class.java,
JsonDeserializer<Any?> { json, _, _ ->
try {
Char(json.asJsonPrimitive.asInt)
} catch (e: Exception) {
null
}
},
)
builder.registerTypeAdapter(
Character::class.java,
JsonDeserializer<Any?> { json, _, _ ->
try {
Char(json.asJsonPrimitive.asInt)
} catch (e: Exception) {
null
}
},
)
builder.registerTypeAdapter(
Char::class.java,
JsonSerializer<Char?> { value, _, _ ->
JsonPrimitive(value.code)
},
)
builder.registerTypeAdapter(
Character::class.java,
JsonSerializer<Char?> { value, _, _ ->
JsonPrimitive(value.code)
},
)
return builder.create()
}
Also, note the implementation of JsonDeserializer, the null has to be inside the catch, otherwise, it would always return null.
With some refactoring, we can simplify this in the following way:
private fun createGson(): Gson {
val builder = GsonBuilder()
val customCharSerializer = object : JsonDeserializer<Any?>, JsonSerializer<Char?> {
override fun deserialize(json: JsonElement, typeOfT: Type?, context: JsonDeserializationContext?): Any? {
return try {
Char(json.asJsonPrimitive.asInt)
} catch (e: Exception) {
null
}
}
override fun serialize(src: Char?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement? {
return src?.let { JsonPrimitive(it.code) }
}
}
builder.registerTypeAdapter(Char::class.java, customCharSerializer,)
builder.registerTypeAdapter(Character::class.java, customCharSerializer,)
return builder.create()
}
What I want to make is a function, that returns itself, so I can call it like this:
foo()()...()
In C# it would be done via delegates:
delegate SelfFunc SelfFunc();
static void Main() {
SelfFunc foo = null;
foo = () => {
return foo;
};
foo()()...();
}
Anticipating questions like "why implement such silly behavior?": I want to sum numbers in a very strange way using single function continues calls: foo(1)(2)(3)() = 6, but in this question I just want to know how to return function itself. Example realization of this method that I made in C#. This is all just for fun and to learn Rust:
static int sum = 0;
delegate dynamic InfFunc(int i = int.MaxValue);
static void InfFuncTest() {
InfFunc f = null;
f = (int i) => {
if(i == int.MaxValue) {
return sum;
}
sum += i;
return f;
};
var g = f;
var value = g(1)(2)(3)();
Console.WriteLine(value);
}
A function that returns itself is possible on nightly.
First you need to enable the features unboxed_closures and fn_traits.
Then you can define a struct which, when called, returns self. The full code looks something like this:
#![feature(unboxed_closures, fn_traits)]
struct SelfFunc;
impl FnOnce<()> for SelfFunc {
type Output = SelfFunc;
extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
self
}
}
Then you can call the function as many times as you want:
fn main() {
let f = SelfFunc;
f()()()()()();
}
Based on #cameron1024's answer, you can "overload" using traits, but you will need 2 structs to handle the empty case properly of foo() (here called Add) without any arguments returning 0.
#![feature(unboxed_closures, fn_traits)]
struct Add;
impl FnOnce<(u32,)> for Add {
type Output = AddImpl;
extern "rust-call" fn call_once(self, args: (u32,)) -> Self::Output {
AddImpl(args.0)
}
}
impl FnOnce<()> for Add {
type Output = u32;
extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
0
}
}
struct AddImpl(u32);
impl FnOnce<()> for AddImpl {
type Output = u32;
extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
self.0
}
}
impl FnOnce<(u32,)> for AddImpl {
type Output = AddImpl;
extern "rust-call" fn call_once(self, args: (u32,)) -> Self::Output {
Self(self.0 + args.0)
}
}
fn main() {
dbg!( Add(1)(2)(3)() );
dbg!( Add() );
}
Playground
If you do not care about the no-args foo() requirement, you can make Add a tuple struct instead and remove AddImpl:
#![feature(unboxed_closures, fn_traits)]
struct Add(u32);
impl FnOnce<(u32,)> for Add {
type Output = Add;
extern "rust-call" fn call_once(self, args: (u32,)) -> Self::Output {
Add(self.0 + args.0)
}
}
impl FnOnce<()> for Add {
type Output = u32;
extern "rust-call" fn call_once(self, _args: ()) -> Self::Output {
self.0
}
}
fn main() {
dbg!( Add(1)(2)(3)() );
//dbg!( Add() ); // doesn't compile
}
Playground
Although I should note that this likely isn't such a great idea, using an slice/iterator would likely result in cleaner code:
fn main() {
dbg!([1, 2, 3].iter().copied().sum::<u32>());
}
Playground
I'm trying to hack together a simple WebSocket client using tungstenite that parses JSON. Most of the code comes from this example.
If I do println!("{}", msg) It works fine, so I'm not sure why the type is mismatched (msg is supposedly a string right?). https://docs.rs/tungstenite/0.6.1/tungstenite/protocol/enum.Message.html
use tungstenite::{connect};
use url::Url;
use serde_json;
fn main() {
let (mut socket, _response) =
connect(Url::parse("wss://www.bitmex.com/realtime?subscribe=trade:XBTUSD").unwrap()).expect("Can't connect");
loop {
let msg = socket.read_message().expect("Error reading message");
let parsed: serde_json::Value = serde_json::from_str(&msg).expect("Can't parse to JSON");
println!("{:?}", parsed["data"][0]["price"]);
}
}
error[E0308]: mismatched types
--> src/main.rs:12:62
|
12 | let parsed: serde_json::Value = serde_json::from_str(&msg).expect("Can't parse to JSON");
| ^^^^ expected `str`, found enum `tungstenite::protocol::message::Message`
|
= note: expected reference `&str`
found reference `&tungstenite::protocol::message::Message`
[dependencies]
tungstenite = "0.10.1"
url = "2.1.1"
serde_json = "1.0.53"
Something like this will work:
use tungstenite::{connect};
use url::Url;
use serde_json;
fn main() {
let (mut socket, _response) =
connect(Url::parse("wss://www.bitmex.com/realtime?subscribe=trade:XBTUSD").unwrap()).expect("Can't connect");
loop {
let msg = socket.read_message().expect("Error reading message");
let msg = match msg {
tungstenite::Message::Text(s) => { s }
_ => { panic!() }
};
let parsed: serde_json::Value = serde_json::from_str(&msg).expect("Can't parse to JSON");
println!("{:?}", parsed["data"][0]["price"]);
}
}
i'm trying to make an async call to a domain. The following code works well if i specify a valid address with json response, but when the address is not valid, i want to be able to catch any possible exceptions.
How can i catch the returned exception?
Here an extract from stacktrace:
Message: Invalid JSON String
...
http.AsyncHTTPBuilder - Exception thrown from response delegate:
groovyx.net.http.HTTPBuilder$RequestConfigDelegate#420db81e
Here the code:
def http = new AsyncHTTPBuilder( poolSize : 1,
contentType : ContentType.JSON )
def futureResult
futureResult = http.request( "http://www.notexistingdomainxyzwq.com/",
Method.GET,
ContentType.JSON ) {
response.success = { resp, json ->
log.info("SUCCESS")
}
response.failure = { resp, json ->
log.info("ERROR")
}
}
log.info("Call started");
try {
while (!futureResult.done) {
log.info('waiting...')
log.info("DONE: ${futureResult.done}")
Thread.sleep(1000)
}
} catch(ex) {
log.error("EXCE ${ex}")
}
log.info("Call completed")
If you call futureResult.get() to block and wait for the result, this will throw the exception which you can catch:
try {
def result = futureResult.get()
log.info( "Done: $result" )
} catch(ex) {
log.error("EXCE ${ex}")
}
I have the following code:
member public this.GetData(uri: string) = async {
let! res = Async.AwaitTask(httpClient.GetAsync uri)
return res
}
When the property res.IsSuccessStatusCode is false I would like to throw an exception, how can I achieve this. The following code won't compile:
member public this.GetData(uri: string) = async {
let! res = Async.AwaitTask(httpClient.GetAsync uri)
match res.IsSuccessStatusCode with
| true -> return res
| false -> raise new Exception("")
}
You certainly need to wrap new Exception(...) in brackets, but that is not sufficient in this case - both branches of the match statement need to return a value, so you also need to insert return:
async {
let! res = Async.AwaitTask(httpClient.GetAsync uri)
match res.IsSuccessStatusCode with
| true -> return res
| false -> return raise (new Exception(""))
}
This is actually easier to write using an if computation which can contain body that returns unit (and throws an exception if the operation did not succeed) - and so you do not need return in that case:
async {
let! res = Async.AwaitTask(httpClient.GetAsync uri)
if not res.IsSuccessStatusCode then
raise (new Exception(""))
return res
}
So the first part is that you need to wrap the new Exception() with brackets to make sure that F# interprets the code correctly.
raise (new Exception(""))
or you can use either of the pipe operators
raise <| new Exception("")
new Exception |> raise
or you can change the type and use failwith
failwith "some message"
Secondly, you need to return from both branches, so prefix raise with return