I am working ti old F# code from Expert F#. However, the example doesn't build anymore.
The following two calls don't seem to exist:
semaphore.AsyncWaitOne(?millisecondsTimeout=timeout)
and
reader.ReadToEndAsync()
Does anyone know what these have been replaced with or if I am just missing a reference?
It's now called Async.AwaitWaitHandle.
AsyncReadToEnd is in the F# PowerPack.
By now, FSharp PowerPack project has been broken up into smaller modules for any further development.
Specifically, the AsyncStreamReader class and the extension methods for the reading from a StreamReader, WebClient, etc. the new project is FSharpx.Async.
1) AsyncWaitOne is now called Async.AwaitWaitHandle.
2) AsyncReadToEnd() extension method does not exists anymore in the FSharp.PowerPack.
It has been replaced with the AsyncStreamReader dedicated type that contains proper asynchronous implementation of stream reading (like ReadToEnd, ReadLine, etc.)
It can be used like that:
async {
use asyncReader = new AsyncStreamReader(stream)
return! asyncReader.ReadToEnd() }
Note: Once you have installed FSharp.PowerPack, the AsyncStreamReader type will be 'injected' in the Microsoft.FSharp.Control namespace
Related
I'd like to use Fable.JsonConverter.
My test code (almost copy this) FableJson.fs is below,
module FableJson
open Newtonsoft.Json
// Always use the same instance of the converter
// as it will create a cache to improve performance
let private jsonConverter = Fable.JsonConverter() :> JsonConverter
// Serialization
let toJson value =
JsonConvert.SerializeObject(value, [|jsonConverter|])
// Deserialization
let ofJson<'T> json =
JsonConvert.DeserializeObject<'T>(json, [|jsonConverter|])
and paket.dependencies file added nuget Fable.JsonConverter
source https://nuget.org/api/v2
storage:none
clitool dotnet-fable
nuget Fable.Core
nuget Fable.Import.Browser
nuget Fable.JsonConverter
and src/paket.references file added Fable.JsonConverter
dotnet-fable
Fable.Core
Fable.Import.Browser
Fable.JsonConverter
But cannnot compile.
~~~ snip ~~~
ERROR in ./src/FableJson.fs
d:/SRC/Repos/Fable/testJsonConverter/src/FableJson.fs(11,4): (11,57) error FABLE: Cannot find replacement for Newtonsoft.Json.JsonConvert::SerializeObject
# ./src/App.fs 6:0-48
# ./src/testJsonConverter.fsproj
# multi (webpack)-dev-server/client?http://localhost:8080 ./src/testJsonConverter.fsproj
ERROR in ./src/FableJson.fs
d:/SRC/Repos/Fable/testJsonConverter/src/FableJson.fs(15,4): (15,62) error FABLE: Cannot find replacement for Newtonsoft.Json.JsonConvert::DeserializeObject
# ./src/App.fs 6:0-48
# ./src/testJsonConverter.fsproj
# multi (webpack)-dev-server/client?http://localhost:8080 ./src/testJsonConverter.fsproj
ERROR in ./src/FableJson.fs
d:/SRC/Repos/Fable/testJsonConverter/src/FableJson.fs(7,28): (7,49) error FABLE: Cannot find replacement for Fable.JsonConverter::.ctor
# ./src/App.fs 6:0-48
# ./src/testJsonConverter.fsproj
# multi (webpack)-dev-server/client?http://localhost:8080 ./src/testJsonConverter.fsproj
What should I do?
#Maslow is right, with Fable 2 we removed Fable.JsonConverter in favour of the library created by the community.
Thoth.Json offers an Elm-like experience where you can decode the JSON manually or automatically depending on your preference. This library also offers a good error message
Fable.SimpleJson a library for parsing and transforming JSON in Fable projects
Thoth.Json is complemented with Thoth.Json.Net to allow you to use the same API on the backend.
I think Fable.SimpleJson also offer supports for the backend, but I am not sure.
You can use the JavaScript native API Fable.Core.JS.JSON.stringify and Fable.Core.JS.JSON.parse(x) but you will have to use unbox/cast to force the type of your Data which is not safe and can break easily.
See here: http://fable.io/docs/interacting.html#json-serialization
On the client side you should use the Fable.Core.JsInterop functions toJson and ofJson.
Fable.JsonConverter is for the server-side only. It uses Newtonsoft.Json, which is a .NET library that doesn't run in the browser. The compile error you're getting is because Fable doesn't know how to convert Newtonsoft.Json function calls into JavaScript.
It can be confusing when you're working with a language that works in one runtime (e.g. .NET) and also compiles into another one (e.g. JS), but you should try to keep a clear mental model where all of your code is running and therefore what it has access to.
The accepted answer is no longer valid. For newer Fable the only thing I've been able to find is Fable.Core.JS.JSON.stringify which calls the browser's built-in serializer.
Also Fable.Core.JS.JSON.parse(x) which returns obj.
I'm trying to create a Sitelet with SiteletBuilder in C#:
return WebSharper.Sitelets.Content.Page(...)
However, the class Websharper.Sitelet contains Content both as Struct and Class.
So, this does not compile.
Versions of Zafir-Libraries are
Zafir 4.0.152.29-beta5
Zafir.CSharp 4.0.152.29-beta5
Zafir.Html 4.0.56.95-beta5
Zafir.UI.Next 4.0.102.33-beta5
How to reference WebSharper.Sitelets.Content proberly?
Or is this indeed a bug?
Thanks for the report, created ticket: https://github.com/intellifactory/websharper/issues/645
I have been testing with having using WebSharper.Sitelets; and then using with shorter form Content.Page(...). C# can resolve this for some reason, although the name conflict indeed exists in WebSharper.Sitelets.dll
I'm trying to explain a weird F# compiler behavior between Release and Debug configurations regarding transitive dependencies. I will use Newtonsoft.Json package as the base dependency here, because that's the furthest I managed to get in pinpointing the issue, and it makes the example a bit less abstract.
Let's create a library project called SerializerProject, referencing Newtonsoft.Json via paket. In this project there is only one module:
module Serializer =
open System.IO
open System.Text
open Newtonsoft.Json
type OptionConverter() =
inherit JsonConverter()
(* only the signature is important, the implementation
and other methods are not interesting *)
override x.WriteJson(writer: JsonWriter, value: obj, serializer: JsonSerializer) =
(* ... *)
let fromJson<'a> (bytes: byte []): 'a =
let s = Encoding.UTF8.GetString(bytes)
use sr = new StringReader(s)
use jr = new JsonTextReader(sr)
let serializer = JsonSerializer()
serializer.Converters.Add(OptionConverter())
serializer.Deserialize<'a>(jr)
Now let's create a second project in the same solution and reference SerializerProject via project reference. I'd like to use fromJson in my new project, that's why I referenced SerializerProject in the first place.
module MyModule =
open Serializer
(* This is here just so we reference the fromJson function *)
let deserializer bytes = fromJson bytes
This is the minimal example to reproduce the behavior.
Now when I build the solution in Debug configuration, everything compiles and works fine. But when I switch to Release, the compilation fails in the second project, in MyModule in the deserializer definition. The exact error message is this:
The type referenced through 'Newtonsoft.Json.JsonWriter' is defined in an assembly that is not referenced. You must add a reference to assembly 'Newtonsoft.Json'
I'm using Visual Studio 2015 Update 3, F# tools (fsc, fsi) show version 14.0.23413.0.
It kind of makes sense, because it's reading metadata of the SerializerProject and finds that public OptionConverter type leaks the type JsonWriter on its public WriteJson method (as well as other types and other methods, but this one is encountered first), but what makes me wonder is why this works in Debug mode and is only a problem in the Release mode.
What kind of extra operations does the compiler do that affect this?
Why is this not a problem in Debug build when the type defined in Newtonsoft.Json really leaks transitively into the second project?
As suggested in the comments I tried referencing Newtonsoft.Json and decompiling the second assembly with ILSpy to see whether inlining turned on by compiler optimizations is to blame here, but even in Release configuration the second assembly looks like this:
call !!0 [SerializerProject]Serializer::fromJson<!a>(uint8[])
The fromJson function has not been inlined to expose the JsonWriter type directly, so there seem to be something more subtle going on.
This isn't a blocking issue, I just made the converter types private as I don't want to use them from the outside anyway, but I'd like to dig deeper in F# compiler inner workings.
I am using analyzer_experimental to parse a Dart file into a CompilationUnit:
import 'package:analyzer_experimental/analyzer.dart';
var unit;
try {
unit = parseDartFile(path);
} on AnalyzerErrorGroup catch(e){
print(e);
}
The above code will catch any parsing errors encountered.
I am also interested in seeing any warnings associated with the file (e.g. 'Undefined name "foo"'). I know that the experimental_analyzer library has the capability to generate these warnings when running from the command line but it does not seem to be possible to get the warnings programmatically, without directly referencing classes in the src folder (which seems like a bad idea).
Is there any way to achieve this?
It's likely this package was very incomplete at the time.
There's now an analyzer package on pub and also a (work-in-progress) STDIN/STDOUT Analyzer Service aimed to help making tooling support easier for IDE extension authors.
I'm trying to translate some code from C# to F#, specifically the code to create a shortcut, from here: http://vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects/Creating_and_Modifying_Shortcuts/ShellLink_Code_zip_ShellLink/ShellLink_cs.asp
The code in C# reads:
[GuidAttribute("00021401-0000-0000-C000-000000000046")]
[ClassInterfaceAttribute(ClassInterfaceType.None)]
[ComImportAttribute()]
private class CShellLink{}
Which I translated to F# as:
[<GuidAttribute("00021401-0000-0000-C000-000000000046")>]
[<ClassInterfaceAttribute(ClassInterfaceType.None)>]
[<ComImportAttribute()>]
type CShellLink() = class end
Unfortunately, when I switch to the F# implementation, I get a runtime error of: "Method with non-zero RVA in an Import". This seems to be the same error as reported here: http://social.msdn.microsoft.com/Forums/en-US/fsharpgeneral/thread/dada2004-5218-4089-8918-eed2464bbbcd
Is there any workaround? I'm trying to port the application to only use F#, so if this can't be written in F# that project is going to have to be rethought.
this looks like a limitation in F# compiler: it cannot define existing COM classes using ComImportAttribute, it only works for interfaces. Can you use this as workaround?
let shellLink =
let ty = System.Type.GetTypeFromCLSID (System.Guid "00021401-0000-0000-C000-000000000046")
Activator.CreateInstance ty