What should I learn if I want to develop desktop apps and I like functional programming? I feel like most of the cool 'new' programming languages are OOP (rust, go, scala).
For desktop apps specifically + functional programming, F# is probably your best bet. On Windows WPF is king, and F# works great. For desktop apps on Linux and elsewhere, you can use Xamarin, GTKSharp, AvaloniaUI...and the list goes on. Desktop apps are a strength of the .NET ecosystem.
WPF has been stagnant for a while, I think they just have a maintenance team on it at MS. UWP is where the new action is supposed to be, but it is limited to store apps.
F# is not compatible with UWP because .net native doesn’t implement the .tail IL opcode so it’s a no go. Moreover WPF allows a wider distribution that UWP which is restricted to Win10.
You can always disable tail calls via a compiler flag. I think the real issue is that .NET Native can't handle very deeply nested generics (although this may have been fixed). There are also issues with reflection in certain cases, but I believe they can be worked around.
True. But WPF is not going to be improved, it is just like WinForms now. UWP has all the modern API goodness (win2d, better rendering) while Microsoft seems to be pushing developers to web for everything else.
Starting a new project in WPF at this time doesn’t make sense.
> I feel like most of the cool 'new' programming languages are OOP (rust, go, scala).
For what it's worth rust and go are not OOP languages. Scala and Swift (to add another new, hot language) have inheritance and OOP features for ffi with their platform langagues java and objective-c respectively. However, the OOP features are largely discouraged and their type systems have more in common with haskell and other strongly typed functional languages. Rust has basically the same type system as haskell and swift with its famed borrow checker on top. Scala, Rust, Swift are all mixed paradigm with their community's' preference for functional design in roughly that order. Go has a totally different type system from the others and is almost entirely an imperative langauge.
OO people always find a way to write OO code in any language. Go, for example, is dominated by such people. Something that could be written in a few lines of code and no hidden state is often a bunch of objects with lots of hidden state. I'm not sure about Rust, but I don't see why it would be different there. It starts with a language having a method call syntax (foo.bar()). Once it's there OOP is inevitable.
Agreed, it's hard to write nice, immutable, functional code in Go. For one, you have to put considerable design effort into make your functions chainable while at the same time support error propagation, which tends to necessitate the use of interfaces (e.g. "Iterator"), which without generics leads to interface{} all over the place.
I think Go works best for applications that don't need any "internal plumbing". For example, one of my projects is a query engine. It takes an AST and plans a pipeline of operators that compose together (map, filter, join etc.). It's pretty damn awkward to write in Go, and type safety often goes out the window. It's something that in other languages (Haskell, OCaml, Rust, Scala and Swift would all qualify) could be expressed with an elegant smattering of union types, generic functions and monadic chaining.
But that awkwardness is because the app is 99% framework (various types and functions being used to compose stuff together), most of which is a big, generic factory to produce a small engine. If your app is all imperative "meat", with little framework, then Go is a much better fit.
F# got mentioned already but I would like to add another vote to it. C# is the first choice for most people when building desktop apps for Windows but F# works exceptionally well too. There is a small but robust community and there are a ton of libraries/tools that you can hook into via .NET.
after some functional programming experience, you may learn that functions just compose more elegantly than objects.
"Objects are a poor man's closures" (NN)
I found myself in that space for a while, but everything kind of made sense when the "Erlang is the most object-oriented language in the market" meme clicked into place: a (micro-)service, an Erlang-style actor and an object are almost the exact same unit of abstraction, applied in different ways. The model is always the same: you communicate by message passing — and, for the most part, you want your objects to be given orders rather than be asked questions.
When I went back to Java, it became evident how damaging the "everything is an object" mentality of Java really is — it really pushes people towards a whole bunch of anti-patterns. One obvious example is that structs are not objects, and you shouldn't try to make them be. Getters/setters are a clear sign that your entity is a struct rather than an object — if you're at that stage, stop trying to apply OOP principles around its design. Another recurring problem is abusing inheritance, and underusing interfaces. I've written maybe 2-3 abstract classes over the last few years, and, when I code review a PR with any abstract classes (or inheritance of any sort) in it, I can almost always get the original author to factor it away while agreeing that it was a problem in the design.
I suggest giving Kotlin a try. Data classes are as close to structs as you'll ever get in the JVM (until Valhalla ships), delegation is crazy easy to achieve, inheritance is heavily discouraged (by having everything be final by default), bare functions and extension functions help keep interfaces clean, and the lambda situation is much better than Java's (receiver lambdas are the language's killer feature, IMO).
OOP as described by java and C++ involves a graph of objects changing each others' state. This is not an orthogonal pattern to functional programming.
If you're thinking of functions operating on immutable objects and returning new objects then that is not typically what we refer to as a OOP pattern though technically it may fit the definition.
I know. The dominant paradigm has changed the definition of the vernacular. Right now the default definition of OOP is the Java and C++ way unless you explicitly state otherwise.
In my career I started off with OO/imperative, then got heavily into functional programming. I came out at the other end strongly preferring immutable objects over struct+procedure function programming. It's a style I consider deeply OO, and still has referential transparency, but which usually gets ignored in these discussions.
I find it to be cleaner than having module M with struct t and functions M.create: () -> t, M.doStuff: t -> 'a. Which is what tends to happen. It just looks like immutable objects for slow learners...
some heropunch community members have expressed their intention to take responsibility for x0[1]. the plan is to build a nice DSL in elixir that binds to nuklear[2]. some of my notes are in the linked repo, but i'm currently focused on other aspects of the toolkit.
really looking forward to seeing where they go with it!
I’m not sure where your perception is coming from. Rust and Scala are more functional than they are OOP. Rust for example uses Hindley-Milner type inference, putting it squarely in the functional camp. And Scala is highly functional as well, considering its use of higher order functions and monads.
> Rust for example uses Hindley-Milner type inference, putting it squarely in the functional camp.
That's not a very good way to characterize functional programming languages. Obviously you can do functional programming without type inference (see Lisp), and type inference is similarly applicable to non-functional languages (see OCaml's purely imperative sublanguage).
Also, as far as I can tell, Rust uses (a modification of) the Hindley-Milner algorithm to infer lifetimes, not types. As languages in the functional camp typically don't have lifetimes, this argument is a bit strange.
Rust uses Hindley-Milner to infer types in general, but there is a conscious decision to require explicit types in function signatures etc. Also, lifetimes are part of all rust's types, they are just usually elided since it would be pretty verbose and unhelpful to always write them out.
By reference to HM, I mean to illustrate that Rust has fundamental similarities to the typed lambda calculus, which has been done more formally by Rust Belt. Additionally, traits in rust are highly similar to type classes in, say, Haskell. Describing rust as a functional language is reasonable, see eg http://science.raphael.poss.name/rust-for-functional-program...
The newest thing in functional languages and UI is haskell + reflex. Reflex is a usable FRP system (not that reactive-banana, et al, were not; just that they were not usability focused at all). Reflex-dom is pretty nice for web stuff, and you can use reflex to build apps with other UI toolkits as well.
If you can afford to exclude windows and linux, Swift.
If you like windows but also want cross platform, C#/F# and Xamarin.Forms or UI or whatever its called. I've heard very positive things about dotnet gui work these days.
I'm spending time with rust to try my hand at game development. As an older developer, it's all a bit foreign to me so I don't really know what's good and what's not.
That having been said, desktop development is something the rust community at large is dedicated to ant interested in. There's already a fee libraries, like Conrod for Piston, gtk.rs, etc but I don't know how these options stack up against industry standards.
C# 7 is a lot more functional and pleasant than the C# 4/5 everybody dismissed years ago.
F# can compile to wherever you need it and you can write functional first and just include it in your nuget built just like you normally would.
If you're adamant about functional, consider dotnet. Of course C# is still very much OOP, that's just what it is. But I find the primary benefits to FP in my own code to be more related to correctness, testability (and therefore more correct) and a convenience in modelling data structures quicker than subclassing. Even with generics, having unions and record types makes it just that much more satisfying.
F# actually has a little micro-discipline called domain-driven programming. Search for that term and you can see how different researchers have used F#'s incredibly flexible type modelling to adapt to their domain and make their code easier for people in that domain easier to understand.
To expand on your point, the most interesting library I’ve seen for desktop GUIs in Rust is “relm”. It’s as the name implies an FRP-like and Elm-inspired library for Rust.
What should I learn if I want to develop desktop apps and I like functional programming? I feel like most of the cool 'new' programming languages are OOP (rust, go, scala).