
Ineffective coding habits many F# programmers don’t have - ingve
https://functional.works-hub.com/blog/Seven-ineffective-coding-habits-many-F-programmers-don-t-have
======
mamcx
Is ironic how most failed to see the main points, and focus in the syntax
(syntax is easy to attack because the cargo cult notion of "syntax not matter
much").

I have learned and used FOR WORK almost a dozen languages now, F# being the
last of the bunch. I totally remove many ineffective coding habits, mostly:

\- Inmmutability

\- The type checker making me aware of problems

\- Not need to over-check for nulls because now I don't need to worry

\- Pattern matching + AGDT are _awesome_. This cut the need to make a lot of
unecessary classes.

\- Make me to think outside over OO. I do this also in Pascal(Delphi) and
python, and hate how C# is OO/Class for all. \---

About syntax:

F# totally cut millons and millons of lines of code! (exagerating!) but more
important: Far less _files_ than similar C# project (and yes, I have made the
rewrites. I do rewrites for life! I work upgrading, fixing, moving, old
codebases most of time).

However, some things that I hate of F#:

\- Whitespaces must be as python. Is better.

\- Not like to rely on type inference. Is a good idea on paper but have the
stupid habit of only work AFTER you write. Put the types manually is better,
IMHO. You get more clarity, ease readability, not need to rely on a IDE, the
types are less obtuse, etc.

Ironically, VS Code show the types as you write but Visual Studio Mac no. I
have both opened some times because this!

So, type inference is net negative for me. Maybe is my pascal love talking
here.

I don't like how everything is "let". I wish it was "let, function, etc".

I don't like the overuse of spaces for everything. And how comas are for
tuples but ; for separate items.

But overall? F# is better than C# most of time.

~~~
mannykannot
You say that "syntax not matter much" is a cargo cult notion. I am not sure
you understand the cargo cult analogy, but I take it that you disagree with
the sentiment, which is itself ironic, given that the reasons you give for
favoring F# are all much more than syntax issues. They could have been the
basis for a more persuasive article.

~~~
mamcx
Ok, is not well articulated:

> F# are all much more than syntax issues

But some of the things that make F# unique are _surfaced with the syntax_. Is
not just there for the sake of it.

Pattern matching is the _most obvious_ thing. The way the syntax present this
aspect is close to perfect...

ie: I'm for fun building a language. I have tried _a lot_ of ways to present
some things, like Pattern Matching. I can't figure a better way without
resorting to weird characters, unicode or text editors that not exist. (I
replace "|" as separator but the basic structure is just the same).

Other ways the syntax is significant is in how it encourage curried functions,
chaining and pipelines (with |>). The pipeline way is something that I truly
_adore_. Wish F# was more into this, IMHO.

Not fan in how let have different meanings, neither the use of "," for tuples.

Also is confunsing why functions with "let sum a b" are truly different to
"let sum(a,b)". Hate this (because suddenly pipelines and curried application
not work anymore).

The making of "inmutable first" and marking some vars as "mutable" is
something truly nice. Could be easier if it was "let" and "var" instead of
"let mutable" but anyway. Is good.

Anyway, as a amateur language designer it make me more aware in how the syntax
make a language better or more ergonomic and lead the way in how use it.

~~~
sidlls
"Close to perfect" according to...you? Arguments from Syntax are closer to
emacs vs vim or K&R vs Allman bracket/indentation flame wars than they are to
meaningfully discussing differences between languages. It's so superficial
compared to so many other things.

~~~
mamcx
I have look at more than dozen languages, probably more (as research in how
build one).

So is not _exactly_ according to me, but how is done in other languages.
Anyway... try to design this, for example, and tell how you do it better ;)

------
knieveltech
I take issue with the notion that comments are "noise".

~~~
eradicatethots
I don’t

~~~
nomel
I've never once come back to my own code, say, three months later, and wished
I had less comments.

~~~
kruczek
I did, although I admit it was only for awful projects, where people used to
comment out code instead of deleting it... hundreds of lines of commented out
code and occasionally one or two lines uncommented in the middle of that. Not
fun to maintain code in such state.

~~~
icc97
Commented out code, is not a comment about the code. It's just someone not
clearing their trash.

------
mannykannot
The twice-implemented requirement mentioned near the start of this article
seems to have the potential for being the basis of an informative case study,
but this was not it - instead, it is just another article pontificating over
the minutiae of syntax (the linked article may have a more informative
analysis, but the link seems to be broken.)

At one point, we read "your abstractions should afford the right behaviours
whilst make it impossible to do the wrong thing." Well, that would undoubtedly
be helpful, but Turing may want to have a word with you about the feasibility
of guaranteeing it. What does F# do in this regard? We are told it does not
have nulls, which is nice, but what does it do to avoid someone introducing
data that are semantically, rather than formally, null values (NaN, for
example?)

The section on testing does not seem to contain anything that is F#-specific.
it mentions QuickCheck, but that has apparently been implemented for many
imperative languages, including C#. Is this sort of thing more effective for
functional languages? There is no discussion of the possibility here.

I am actually persuaded that there are benefits to functional programming, but
articles like this paradoxically give the impression that there is not much
substance behind the large claims.

The first thing I would like to know about the case study was whether the
implementers of one version benefitted from the problems encountered by those
of the other, especially with regard to getting the requirements nailed down.

~~~
brians
Turing hardly prevents it; indeed, by the Church-Turing thesis, shows us how
it’s done: write an abstract model of your problem space. This is your types
and type functions (like Option/Some/Maybe). Write a type that is the theorem
claiming you get your output from your input. Now you guarantee you cannot do
the wrong thing. Affordances for the right behaviors? Those are library
functions you build bottom up, or assemble from a library of structures
(functor, monad, etc.) and your types. As all affordances, there are art and
craft here.

On semantic nulls, the compiler typically enforces completeness on case
analysis.

~~~
mannykannot
Yes, I should have scrubbed that paragraph and started over, to say something
like eliminating nulls is only part of the problem, and you still have to do
everything right, starting with your abstract model of the problem space. With
regard to semantic nulls, I offered NaN as an example, but I was thinking of
the case where the programmer introduces what is, in practice, a semantic null
value for one of his user-defined types - something that should be
distinguished as a special case, but isn't.

------
weberc2
I like F#, but I think the "F# has objectively better syntax" claim needs a
lot more support than the "signal-to-noise-ratio" argument. I don't know of
anything that suggests that humans are better at parsing whitespace-delineated
arguments than say, comma-delineated. My experience (probably biased similarly
to F#'s target audience generally, possibly with above average exposure to
functional languages) suggests that C-like syntaxes are easier to read.

~~~
aloisdg
Ask Python dev. Most people found Python code easy to read thanks to
whitespace.

~~~
stephengillie
It's the YAML/JSON debate - would you rather have ugly curly brackets or
annoyingly-precise whitespace? Personally, I choose ugly brackets, but I know
many prefer the annoying whitespace.

~~~
tonyarkles
I always find this funny, because I indent my C/JS/C#/Java/whatever-other-
curly-brace code exactly the same way Python expects me to indent it, so it's
never really been an issue.

Every time someone complains about significant whitespace, my first reaction
is "what indentation style are you using where that's an issue?!"

~~~
vorotato
Yeah I frequently switch between F# and C# and I literally cannot tell a
difference in effort. I assume the complaints are more out of familiarity than
anything else. I have never had issues in either language.

------
vkou
The visual honesty example is dishonest.

It uses two indents for indenting the parameter list of the function, and two
indents for indenting the body of the function.

Most indentation conventions suggest four space indentation for breaking up a
list of parameters, and two space indentation for the body of a {}. In order
to avoid the problem that the example criticizes.

~~~
Ensorceled
My reaction was similar - "Who formats code like that?"

It's pretty easy to be better when starting from such a low bar.

------
sidlls
The link to the article with the comparison doesn't work to me. Often what I
find in these articles is that the second implementation takes much less time
and has less code and fewer bugs primarily because of the lessons learned the
first time round. It has almost nothing to do with the language of
implementation.

------
maxxxxx
I hope F# people can do better than this. Not very convincing.

~~~
melling
Well, if the code does the same thing and it’s 1/10 the size, that would be
convincing. Don’t recall seeing this sort of comparison for ML languages in
the past, however.

~~~
jackmott
not usually 1/10 almost always at least 1/2, sometimes approaching 1/10 if a
class hierarchy is a large % of the project and it can turn into a
discriminated union.

------
xelxebar
Completely off topic, but this site along with a few others like StackOverflow
seem to hijack my browser history and break the back button. In order to back
out of their domain, I have to quickly bang the back key twice.

I have no idea what causes this. I even run with Javascript completely
disabled.

------
stephengillie
Readability is why I use "closing flags" so I don't get lost in a sea of
closing curly brackets. Example:

    
    
      if ($TreeHasLeaves) {
      	Write-Host -f green "The variable  TreeHasLeaves is $($TreeHasLeaves)"
      }; #end if TreeHasLeaves
    

My "GilLang" auto-adds these closing flag comments after each closing bracket
- currently it only supports Powershell, but the goal is to streamline basic
coding (if/then, for/foreach, do/while, try/catch) in many languages. To
create the above function statement, curly brackets included, just type use
"New-FunctionStatement if TreeHasLeaves -Powershell".

~~~
na85
rainbow-delimiters-mode is great for this, if you're an emacs user.

~~~
stephengillie
Is this a good example?[0]

That would be helpful, and I hope Notepad++ gains the feature. Notepad++ does
have a bracket helper that highlights the other bracket, but flagging the
closing bracket helps when there are several brackets.

[0] [https://raw.githubusercontent.com/thblt/eziam-theme-
emacs/ma...](https://raw.githubusercontent.com/thblt/eziam-theme-
emacs/master/screenshots/rainbow-delimiters.png)

------
Grustaf
"controlFactoryFactory" seems to me a pretty apt name for a factory that
creates controlFactories, if that's whatbitbis. What else could you name it
really? "controlMetafactory" perhaps.

------
johnnyb9
I wonder what version of C#? C# 7 and 6 are less verbose.

~~~
mathw
Only in a few areas.

------
dgudkov
The idea behind the article is good, but the implementation leaves to desire.
I can confirm that F# develops good habits in a C# programmer. My favorite
acquired habits are:

1\. Intolerance to nulls and absence of object intializers in constructors.
Use of zero objects a-la Array.empty.

2\. Semantic typing even for simple types (e.g. type Name = string).

------
Roboprog
Forgive me if I read this article as "Scala vs Java", since I'm on the JVM
instead of .NET :-)

~~~
Roboprog
Not that I'm that enamored with Scala, just that Java sets the bar so very
low.

------
vorotato
“The C# project took five years and peaked at ~8 devs. It never fully
implemented all of the contracts. The F# project took less than a year and
peaked at three devs (only one had prior experience with F#). All of the
contracts were fully implemented.”

wowzers

------
sremani
I know for sure I am "stealing" some one else's analogy here (apologies in
advance). In .net world, C# is the lego blocks and F# is the clay.

~~~
ahelwer
I have no idea what this analogy could possibly mean.

~~~
Ensorceled
My kids stopped playing with clay and play dough and graduated to lego at
around the age of four.

~~~
vorotato
Too bad, they could be designing cars :P. (car designers still build their
model in clay)

------
hardlianotion
'Many' is the weasel word here.

~~~
arwhatever
I've been able to use F# at work for a few months now and I'm absolutely
enamored with it.

But I have not yet had any of what I call "ints, strings,and for loops-only
developers," the folks who never really grasped O.O. very well at all,
contribute to the code. I'll be eager see how that goes.

~~~
hardlianotion
I am very enthused about functional languages like F# - don't know much about
F# particularly and respect rather than love C#.

I just find comparisons of this kind slightly off-putting.

It's always an interesting time when you share your lovely clean concept with
potential philistines - hope your project's exposure to your loop-community
goes well.

------
201709User
Times whitespace misused as meaningful: C# - 0, F# - 38255.

Times had to re-order files to build a project: C# - 0, F# - 19.

Experienced non-arrogant developers found for hire: C# - 10000000, F# - 12.

~~~
Roboprog
How many frustrated developers are identified as "arrogant"?

I for one am tired of OOP (a la Simula 67) presented as the be-all and end-all
:-(

The functional programming guys were right, and C++ set back the industry
several decades. (better to have both FP and OOP, but OOP-only stinks)

~~~
goatlover
C++ has never been OOP only. You're confusing it with Java.

~~~
int_19h
C++ has never been OOP only, but it arguably introduced (Simula-style) OOP to
mainstream commercial development. Java wouldn't look like Java if it wasn't
for C++.

