4 ms·
You might like to try Fable and F#. I’ve been looking at it since playing with Reason and Bucklescript, and so far I’ve found Fable much easier to use and more
by jordwest 9y ago
You might like to try Fable and F#. I’ve been looking at it since playing with Reason and Bucklescript, and so far I’ve found Fable much easier to use and more featureful. The syntax is essentially the same as OCaml, plus it’s whitespace aware.
F# has implicit `+` for basic types (though it’s not quite modular implicits). It also has a really nice syntax for async computations, similar to `async/await`. JS interop is much easier too. It can also run on the server with .NET core if you don’t want to use node.
The output JS is slighter heavier and less optimised than Reason/Bucklescript, and compile times slighter slower, but at the moment those are trade offs I’m happy to make
- nozzlegear 9y agoI'll second the recommendation for F# and Fable. I'm currently working on my first project with it, where both the client and the server run F# and can share code/types. I haven't been this happy with a stack in a long while. My one complaint is how... salty some members of the F# community can be, mostly regarding the rest of the Microsoft-backed .NET ecosystem.
- raphinou 9y agoI would be interested to know how you share code between client and server. Can you share info/code? Having one code base like with ocsigen would be even better. Anything like that available?
- bad_user 9y agoThe "+" in F# is really awkward because it tries catering to both the ML type system it got and to the .NET type system underneath, inherited from C#. This is a problem because when type inference kicks in for plain functions, usage of that "+" will make the compiler assume "int". But worse, "+" in C# is not a method, but a static method and the compiler basically does magic, because you don't have this behavior for plain static methods and you don't have a generic interface in the language for "+", there's no Number, no Monoid and static methods themselves in C# can't be polymorphic. The whole notion of "static methods" is broken btw and have nothing to do with OOP. The only purpose of static methods is to enforce visibility rules and this made some sense in C++, where you could have functions living outside of classes, but even there the real problem is the lack of useful namespacing. And F# inherited this behavior, F# inherited static methods, along with math operators described as static methods. So in order to abstract over things that have "+", which is really needed in F# otherwise you can't express really basic things for an FP language like "List.sum", you have to (1) use inline functions, which aren't translated directly to .NET functions and (2) use a really awkward signature that instructs the type system that the type has a "+" static method that it can use, e.g... > let sum x y = x + y;; val sum : x:int -> y:int -> int > let inline sum x y = x + y;; val inline sum : x: ^a -> y: ^b -> ^c when ( ^a or ^b) : (static member ( + ) : ^a * ^b -> ^c) So this signature is really interesting — the type system is saying that our "sum" needs either an A type or a B type and one of them should have a static "+" defined, doesn't matter which one. This is close to how type classes work in other languages, however for the F# compiler this is magic that doesn't scale and making use of "static methods", a flawed concept, a signature that can't be encoded in .NET's type system and therefore the function is forced to be "inline". Which is another problem, because in F# inline functions are more like macros, or in other words these "inline" functions are not values. As soon you try using one as a value, it gets materialized and you loose the type info. So it is very ephemeral. Given this, frankly, I would rather have OCaml's operators. At least they are plain functions.
- pjmlp 9y agoI never understood the complaint about static methods regarding not being OOP. It is not much different from class messages in Smalltalk.
- bad_user 9y agoSmalltalk is not a statically typed, nominally typed language, Smalltalk is dynamic and in Smalltalk classes are objects themselves, so any comparison to Java, C# or F# does not apply. This is relevant in the context of OOP because in OOP when you talk of methods, you talk of single-dispatching, polymorphism and the Liskov substitution principle. Static methods are just plain functions tied to classes from an era when people thought having classes everywhere is actually a good idea, in C# and F# also tied to weird, magical compiler rules around operators. Speaking of Smalltalk and OOP, operators like "+" in languages like Smalltalk are object methods and can be used in generic functions doing polymorphic calls. In OCaml they are plain functions with no overloading. In Haskell they are functions requiring type classes to work, sort of like what F# is doing, but non-broken. Btw, if you're wondering from where the convention of using static methods for operators comes from, that's another relic of C++, a language not known for elegance, finesse or for being a good OOP language.
- pjmlp 9y ago> This is relevant in the context of OOP because in OOP when you talk of methods, you talk of single-dispatching, polymorphism and the Liskov substitution principle. Which also apply to Smalltalk. > Static methods are just plain functions tied to classes from an era when people thought having classes everywhere is actually a good idea, Using GNU Smalltalk serialization syntax, Object subclass: #MyClass. MyClass class extend [ myClassMethod [ ^ 'Hello from class method' ] ] Transcript show: MyClass myClassMethod. Using Java as example, I see no difference from class MyClass { public static string myClassMethod () { return "Hello from class method"; } } System.out.println(MyClass.myClassMethod()); > Btw, if you're wondering from where the convention of using static methods for operators comes from, that's another relic of C++, a language not known for elegance, finesse or for being a good OOP language. Better know C++, before bashing it. In C++ operators can be defined as member functions and participate in inheritance resolution except for operator=. I guess you are mixing C++ with C#.