Make no mistake, it's a cool language that I'd love to be good at. The code always looks elegant, I'm just terrible at writing it.
Make no mistake, it's a cool language that I'd love to be good at. The code always looks elegant, I'm just terrible at writing it.
Unfortunately there's some level of .NET tooling you need to understand before you can do much today, and several .NET concepts creep in with that.
The good news is that .NET Interactive is shaping up to be a great way to avoid most of that. At least so far all you need to do is install the .NET SDK, then install a VSCode plugin and you're good to go - just write code like you would in a python notebook, and acquiring packages is even easier than in Python: https://github.com/dotnet/interactive#notebooks-with-net
The hello world server:
open Wiz.Server
open Wiz.Context
open Wiz.Route
let myHandler ctx =
ctx |> sendText "Abra Kadabra Kalamazoo!"
let myRoutes = [
get "/" myHandler
]
genServer()
|> setRoutes myRoutes
|> runF# currently seems easiest for c# dev to get started, but c# devs have almost no incentive to do so.
"Python needs to appeal to C# developers and other developers...
Python seems easiest for PHP devs to get started, but C# devs..."
And, the truth is, no, Python doesn't need to do that at all. It just has to be the best Python it can be.
Whereas, if you look at the examples in the Giraffe framework, you need to do a bunch of dotnet boilerplate. https://github.com/giraffe-fsharp/Giraffe#doing-it-manually
open System
open Microsoft.AspNetCore.Builder
open Microsoft.AspNetCore.Hosting
open Microsoft.Extensions.Hosting
open Microsoft.Extensions.Logging
open Microsoft.Extensions.DependencyInjection
open Giraffe
let webApp =
choose [
route "/ping" >=> text "pong"
route "/" >=> htmlFile "/pages/index.html" ]
type Startup() =
member __.ConfigureServices (services : IServiceCollection) =
// Register default Giraffe dependencies
services.AddGiraffe() |> ignore
member __.Configure (app : IApplicationBuilder)
(env : IHostEnvironment)
(loggerFactory : ILoggerFactory) =
// Add Giraffe to the ASP.NET Core pipeline
app.UseGiraffe webApp
[<EntryPoint>]
let main _ =
Host.CreateDefaultBuilder()
.ConfigureWebHostDefaults(
fun webHostBuilder ->
webHostBuilder
.UseStartup<Startup>()
|> ignore)
.Build()
.Run()
0If you plan to use Python you have to learn some Python libraries.
I like how well written F# code is less verbose while being very readable.
I want to learn another language. I was thinking about Go, Rust and Kotlin. I excluded Kotlin because it seems it doesn't bring me much value over C# and I excluded Go for the same reason.
I dabbled a bit in Rust, but so far I don't like it's verbosity, the fact that it is boiler plate-ish.
So I reminded myself of F# and started learning that. I know that it has a huge disadvantage compared to the others, it is far less popular, but on the other hand, I can use F# in the same projects I use C# and some of the thing I learn while learning F# might be applicable to C#.
I feel that F# is a niche language mainly because of of two things: Microsoft doesn't care much about it to push it and help it to thrive. And they don't push it because it has a small community. I seems that Microsoft is investing more resources in Python or Java than in F#. The other thing is that the largest community sees it as a Microsoft language and that is enough of a reason not to touch it.
Whatever growing adoption F# has its due to efforts of it's tiny but very enthusiastic community which is helping it to jump some barriers like frontend programming.
Most of introductory material I found was good in explaining functional concepts, lisp approach to solving problems etc, but I thought assumed a working knowledge of the JVM ecosystem.
For someone utterly unfamiliar to Java/JVM world would find clojure extremely baffling, cryptic error messages, needing to be familiar with the rather large java standard library, etc.
While the clojure ecosystem has a lot of wonderful, bright and helpful people in it, and clojure itself is technically impressive (esp. its collections implementation), the new user experience isn't great.
I'm not an experienced emacs user, so that makes it doubly difficult, as the ironed-out workflows seem to assume that you are (which is fair, as emacs and lisp are like peanut butter and jelly). However, these days it's fair to assume that a new clojure user is probably learning 'clojure', 'lispy ways', 'java/jvm', and 'emacs' simultaneously.
I think that calva/vscode has a lot of potential to drop emacs off that list, which is welcome, as its learning curve alone is legendary. If you look at that list, it should not be surprising that the community is small. There's so much to learn that I it seems too much to even start.
I highly recommend 'The Little Schemer' if someone wanted to tread the same ground. Such a strange and fun little book.
You can use Babashka https://github.com/babashka/babashka for a quick and dirty setup to get you up and running quickly. That is also useful for scripting some things. You might also try shadow-cljs + ClojureScript, if you are more at home in the Node.js/ Browser JavaScript ecosystem and want to do something with it. There is a new "(Not)Babashka" but built on ClojureScript: https://github.com/borkdude/nbb that might be interesting as well.
I have found this video by James Trunk: https://youtu.be/C-kF25fWTO8?t=848 to have a very nice live coding example.
Borkdude is a total boss; babashka and clj-kondo are amazing.
Also, don't get me wrong, I reiterate that I already love clojure, I just wish there were fewer and lower barriers for others to join in.
I realize there are already people on that case like https://practical.li/, and are doing an excellent job. I also think that things like https://github.com/Olical/conjure are pretty awesome, being predominantly a vimmer.
It is a hard to swallow truth, but guest languages really require understanding of the underlying platform.
Another example, no matter one's opinion on C or JavaScript, mastering them is a much more confortable life on UNIX/POSIX platforms and browsers than trying to pretend they aren't there.
It can also be frustrating if you know a little OO (but not how Java does everything) and then try to learn a functional language that sits on top of one of these OO tar pits of an ecosystem. I can write Python classes, but seeing the complicated mess of Java is frustrating as that has to be learned as well. Nothing against Java btw (it has its place), but it does seem to require a lot of boilerplate.
That said:
I think that Java is best understood as an enterprise programming language, not as an object-oriented one.
There's a very peculiar class of programming languages that are a product of a specific period of history. At the time, companies were looking for ways to scale beyond the limits of the then-dominant procedural programming paradigm. But they had a lot of existing investment in it, and so teams were naturally hesitant to abandon it entirely.
This situation created an ecological niche that allowed a very peculiar class of programming language to take root. Java and C++ are the best-known examples, but there were others such as Objective-C. C# and Visual Basic.NET are probably the last notable examples. These were multi-paradigm languages that layered object-oriented features on top of procedural bones. Earlier examples such as C++ and Objective-C made this quite explicit, and were likely to even have their atomic types not be objects. Later examples eliminate some features such as non-object types and global functions and variables, but still retain much of their procedural heritage if you know what you're looking for. Probably the most notable one here is a tendency to favor explicitly state-oriented idioms over properly encapsulating state.
Java falls somewhere in the middle. It has later features like full-fledged garbage collection, but lacks others such as a consistently object-oriented type system.
I think that its tendency toward boilerplate directly reflects its stage in this evolution. Basically, what we perceive as boilerplate is really a hold-over from how procedural languages tended to be generally less declarative - it was up to the programmer to handle a lot more stuff for themselves.
In some very large OOP codebases adding features or fixing bugs becomes a nightmare. Every small change you make will break hundreds of tests and while you fix the code to pass those, you will break other tests. Thing that can take days at most in sane codebases might take weeks.
Or that spot we were 100% certain was a bottleneck as it clearly wasn't micro-optimized C code, shows 0.1% hit on the V-Tune profiler.
(That, or you should not have made the change that way in the first place. Much like best practices for API changes involve shipping a new version in parallel and then slowly migrating everything over to it, a breaking change to the behavior of a class that really does have a legitimate reason to be used pervasively - say, a collection - shouldn't be done by just suddenly breaking all the code that uses it.)
Which speaks to exactly the distinction I'm trying to draw when I say, "a tendency to favor explicitly state-oriented idioms over properly encapsulating state." Note that simply sticking getters and setters on your state is not the same thing as encapsulating it.
It's kind of hard to explain the difference except by example, so I'm not really prepared to dive into it here. To be honest, I think the best way to get a feel for it is to read and understand the source code of an early Smalltalk system. Smalltalk-80 is small enough that one can get a decent feel for how everything works in an evening or two.
Chapter 1: install and learn the JVM
Chapter 2: Emacs
Chapter 3, finally start learning Clojure if you made through the first two chapters. Those first two chapters are going to filter out quite a few potential Clojure learners.
It's a cliche saying, but for me F# just works! (tm)
I'm a huge fan of F#, but I had the advantage of knowing .NET first.
Also there are lots of learning resources here: https://fsharp.org/learn/ some for guys coming from scripting languages like Python. As a matter of fact, F# can be used for scripting, too.
#r "nuget: FSharp.Data"
And it pulls that third party package into your script context. Its kind of empowering when I can just copy and paste script text to my colleague (e.g. email/slack) and all they need to do is copy/paste the text into a single text file and it just works third party packages included with a vanilla .NET 5+ installation. Just run 'dotnet fsi scriptFile.fsx`. Auto-complete picks up all the new types as well.
Documentation seems pretty straightforward to me: https://docs.microsoft.com/en-us/dotnet/fsharp/tools/fsharp-...