4 ms·
F# is the place where you can unleash the power of your core developers and make objects fully usable by an army of C# developers. When I used it no one wanted
by fleitz 16y ago
F# is the place where you can unleash the power of your core developers and make objects fully usable by an army of C# developers.
When I used it no one wanted to learn F#, but if I put a nice OO interface on top of whatever I wrote, packaged it as a DLL the other devs would be happy to use it.
F# isn't just cool, it will make you write better code, faster. The zen of it makes you follow a better path. Think about how many bugs go away when you make all sides of an 'if' 'else' block return the same data type.
Think about how much more sense returning an out parameter as a tuple makes.
I'd much rather write
let value = match dict.TryGetValue("foo") with
| (true,val) -> val
| (false,_) -> "default"
Than
string value;
if(!dict.TryGetValue("foo", out value)){
value = "default";
}
Also, if you're using a match statement and forget to handle the false case, the compiler will scream at you. In C# you're on your own. Also, in C# in this case you can't even use var because you're not initializing it.
The other thing about F# is that it's FAST, fast like beating C at the burrows-wheeler transform.
- Gonsalu 16y agoFAST? It's still .NET. Regarding you example, I'd much rather write value = dict.get('foo', 'default') in IronPython.
- MichaelGG 16y agoI'm not familiar with python - does it have some magic global sentinel value to indicate "not found"? Or how do you handle that case with that 1 line of code? Secondly, saying "it's still .NET" is similar to saying "it's still x64". The F# compiler does a lot of transforms on code that the C# compiler does not. In some cases, this can result in better IL and better JIT'd code. Also, having inlining support at the compiler level can be very handy sometimes.
- fleitz 16y agoYes, good points MichaelGG, one of the really nice things about the F# compiler is that it can inline higher order functions, so if you pass a function to another it may create a custom piece of code with your passed function inlined. I wasn't sure if you were referring to C style inline support, which C# does have (in the .NET JIT). Like C the inlining in F# is just a suggestion to the compiler. So you can write code that is optimal from a design point of view (abstractions, etc) and the compiler will turn it into optimal code from a performance point of view. See http://flyingfrogblog.blogspot.com/2009/07/ocaml-vs-f-burrows-wheeler.html http://flyingfrogblog.blogspot.com/2009/07/ocaml-vs-f-burrow... for a much better explanation.
- MichaelGG 16y agoI don't think that F#'s inline is just a suggestion. Hat types (^a) aka statically resolved type variables, require inline methods to actually be inline. Same way you can't have inlined recursive functions.
- jdh30 16y agoYou can nest a recursive function inside a non-recursive one and inline that.
- masklinn 16y ago> I'm not familiar with python - does it have some magic global sentinel value to indicate "not found"? No, it has a different method for failable search. The purpose of `get` is specifically to handle "provide a default value in case the key is not found". > Or how do you handle that case with that 1 line of code? dict[key]
- xiongchiamiov 16y agoYou can also use defaultdict[0], or define the __missing__() method[1] yourself on a dictionary you receive from someone else's code. In either of these cases the "not found" value will be whatever you decide it should be. [0]: http://docs.python.org/library/collections.html#collections.defaultdict http://docs.python.org/library/collections.html#collections.... [1]: http://docs.python.org/library/stdtypes.html#dict http://docs.python.org/library/stdtypes.html#dict
- rlmw 16y agoUpvoted because that's good code reuse in the scenario that you only want to store a default value, and I can see why you replied to the commenter with it. It doesn't necessarily work so well in the scenario where you want to perform some operation if there isn't a value. Or if default needs to be computed. I'm assuming that the idiomatic way of doing this in python would be: try: value = dict['foo'] except KeyNotFound: value = do_something_interesting() dict['foo'] = value If you could pass a function in as a default of course this point is moot!
- popleft 16y agoSee collections.defaultdict in the standard library -- http://docs.python.org/library/collections.html#collections.defaultdict http://docs.python.org/library/collections.html#collections....
- masklinn 16y ago> It doesn't necessarily work so well in the scenario where you want to perform some operation if there isn't a value. No, but that's not what the example he replied to does.
- fleitz 16y agonamespace Org.DictionaryExtensions = type Dictionary<'T> with member x.get(key,defaultValue) = match x.TryGetValue(key) with | (true,val) -> val | (false,_) -> defaultValue There fixed that for you, now you can do, dict.get("foo","defaultvalue") in whatever CLR language you like. :) As for fast and knocking .NET you're not seriously suggesting python are you? Runtime method lookup is not exactly what I think when thinking fast.
- Gonsalu 16y agoI wasn't knocking .NET; I had the idea that coding something in C# or F# would result in the same IL output, which, after reading MichaelGG's reply, I realized was completely wrong... Regarding Python speed, I know it's pretty slow, especially the IronPython implementation.
- mahmud 16y agoCL (setf value (gethash "foo" dict "default"))
- kenjackson 16y agoHmmm... I'm slowly being convinced.
- masklinn 16y ago> let value = match dict.TryGetValue("foo") with > | (true,val) -> val > | (false,_) -> "default" groan let value = findWithDefault "default" "foo" dict or case M.lookup key dict of Just v -> v Nothing -> "default" (and for anybody who wants to whine about parameters order, please remember — or discover — that partial application is extremely frequent in Haskell and MLs, and try to read the parameters order in this light, you will be enlightened)
- timrobinson 16y agodict.TryGetValue is an odd example here -- idiomatic F# for a map lookup would be: let value = defaultArg (Map.tryFind "foo" dict) "default" or match Map.tryFind "foo" dict with | Some v -> v | None -> "default"
- masklinn 16y ago> dict.TryGetValue is an odd example here I sure as hell hope so, but that's what fleitz used.