Unfortunately that syntax is a little troublesome to use.
To enable it, you need to add the --compiling-fslib flag, which basically declares "hi i want to build a stdlib, I know what I'm doing (the flag is undocumented btw)" and as a result it doesn't include the FSharp.Core library and all the built-in modules.
So your code fails to compile because it doesn't know 'string' or 'printf', AFAIK manually adding the reference isn't enough, you would need to statically include all the FSharp.Core source code.
I know that .NET is cross-platform, that was not my point. I'm referring to the parts where the article specifically mentions Windows API. How do I do the same on macOS and Linux? Is it even possible?
Nice hack. What happens if you run it on an unsupported platform? At the very least, I'd expect a runtime exception, ideally on startup. But how do you check whether you can actually evaluate that assembly with the given ABI?
Would probably break something I haven't thought about.
Also the whole task vs async confusion is a bit difficult to wrap your head around. I understand .net6 introduced task {} CE, but you still need to have two stories in your head and convert back and forth and use async {}
Got the same vibe reading this as I did when introduced to Turbo Pascal 7's inline x86 support back in the day. Very seamless and absolutely fantastic for games/demo programming in particular :-)
The problem with methods such as GetCPUCyles or GetCPUCoreId is that .NET delegate calls are never inlined. Unmanaged calli calls are not inlined either. PInvokes could be inlined but have their own overheads for managed<->native transition. These overheads could be higher than a small method body. It would be really cool to generate function pointers with the default managed calling convention, basically what JIT does for normal methods. I mean, packing assembly into the body of a managed function, which has a chance to be inlined.
As someone who wants to learn it and has never used the .NET ecosystem, do I need to become familiar with the standard library and packages through C# first or is it okay if I dive directly into F#?
As a C# developer with no F# experience besides looking at code in articles like this, I don't see any reason why you'd need to start with C# if you're just looking to learn F#.
You don't need to start with it, but you do need to understand C# code to actually use most of .Net and 3rd party libraries. Same when you're using another language than Javascript that compiles to Javascript and same with the JVM and Java, I guess.
To start learning you don't need any C# experience, to build practical things you will probably need to develop a little, to be able to interact with libraries in the C# ecosystem.
I was in a similar position when I started learning F# - I'd say start with F#, but you will likely need to be able to read through some of the C# examples to work out how to do common things that rely on the .NET standard library if you haven't worked with .NET before (for example, if you want to read the contents of a file into memory, it's simple, but the examples on the MS site are in C# here and would need a small amount of translating: https://docs.microsoft.com/en-us/dotnet/standard/io/how-to-r...).
The CE mechanism is great. One little known trick, is you can add a magic member "Quote". The impl. being `member _.Quote () = ()`, and that will result in the Run method receiving an Expr tree representing the entire computation. You then have the ability to take that expr tree and convert to another language e.g. sql, cuda, etc.
I used it on a project where I converted the expression tree to a graph query language "cypher".
24 comments
[ 5.3 ms ] story [ 67.2 ms ] thread> First, F# doesn’t support function pointers
As an experiment, can you work around this with the (deprecated) inline CIL operator: (# ... #)
https://stackoverflow.com/questions/15968054/what-is-the-syn...
To enable it, you need to add the --compiling-fslib flag, which basically declares "hi i want to build a stdlib, I know what I'm doing (the flag is undocumented btw)" and as a result it doesn't include the FSharp.Core library and all the built-in modules.
So your code fails to compile because it doesn't know 'string' or 'printf', AFAIK manually adding the reference isn't enough, you would need to statically include all the FSharp.Core source code.
https://dotnet.microsoft.com/en-us/learn/dotnet/what-is-dotn...
AFAIK you cannot get the RID at runtime, but you can easily set the RID of your program/package to the supported platforms only
https://docs.microsoft.com/en-us/dotnet/core/rid-catalog
I'd avoid assembler unless its separated into an architecture specific file. Otherwise this hack is asking for trouble.
One thing I don't get about the async story in Computation Expressions is the sudden need for you to think about return/return!
Couldn't CE continue to use "return by last statement" and then do the CE-invoking version with exclamation mark in the end?
let private readUrls () = async { (IO.File.ReadAllLinesAsync "urls.txt" |> Async.AwaitTask)! }
Would probably break something I haven't thought about.
Also the whole task vs async confusion is a bit difficult to wrap your head around. I understand .net6 introduced task {} CE, but you still need to have two stories in your head and convert back and forth and use async {}
Also funny I never really understood C# / .NET packages until F# because it's way simpler and less abstracted.
I used it on a project where I converted the expression tree to a graph query language "cypher".