
Function Currying in Go - Insanity
https://medium.com/@meeusdylan/function-currying-in-go-a88672d6ebcf
======
ThreeFx
Compared to other languages, I find Go's syntactic support for partial
application and currying lacking, and every http.HandlerFunc I weep for the
redundancy I create.

I get that that is Go's design philosophy, but IMO a little syntactic sugar
would be nice.

~~~
stunt
GO syntax is very regressive comparing to where we hopped programming
languages should go.

I believe GO success is partly because in recent years, we have many new
specialized engineers that programming isn’t their main focus (DevOps, Data
Scientists, SREs) and naturally they are looking for tooling with shorter
learning curve.

Also when you consider how many developers have a hard time to learn GIT after
so many years, you realize why companies need something as simple as GO
comparing to Rust, or Java comparing to Scala for instance.

~~~
F-0X
>GO syntax is very regressive comparing to where we hopped programming
languages should go.

Speak for yourself maybe, but I appreciate Go's overall style. You also
mention Rust and Scala in your post. If that is to be the future of language
syntax, I should quit.

~~~
shantly
I like that I can dive into pretty much any Go code and it won't be doing
anything basic some way I'm not used to or can't very quickly figure out
without having to look anything up. Kinda like Java in that regard, but even
more so, plus way less verbose.

I mean it's gotten better but take Javascript where just a few years ago
fundamental branching & execution order and might be provided by some library
and it wasn't always _the same one_ (thinking especially of various competing
promise libraries) or friggin' imports might look different. Or Rails where
you might have a codebase come across your laptop that's in some version you
haven't used recently and using a bunch of libraries you're not used to and
now half the symbols in a given file aren't defined there or anywhere else
that Grep can find and it's unclear where they even come from, so it's off to
the docs for a bunch of abandoned gems to get any sense of what's even going
on.

Go mostly avoids that sort of deeply unproductive junk. It does achieve that
by not providing certain things, plus static typing (thank god for TypeScript,
finally some sanity). I'm OK with that. I don't use it as my daily driver but
I'm never even a little sad to drop into or contribute to a Go codebase, and I
don't need a huge margin of uncertainty on the question "how fast can you get
up to speed with this?" for Go code, which I can't say of just about any other
language, sight-unseen.

~~~
erik_seaberg
If experts' code never becomes more clear and concise than novices', there's
no payoff for getting better with the language, and nobody ever really gets up
to speed.

~~~
nemothekid
> _there 's no payoff for getting better with the language, and nobody ever
> really gets up to speed._

Or maybe it's an indication that I should spend less time playing code golf
and more time building what I actually set out to build.

I'd imagine an expert could write a better, performant database than a novice
and the fact that can be achieved in language that will effectively
communicate to a novice is arguably a good thing.

~~~
erik_seaberg
Novices should see queues and sorted sets by their proper names. They should
see reduce(map(filter(…))), not big loops that inline all three written from
scratch repeatedly because experts didn't want the compiler doing work that
might make it slower.

------
jtdev
Call me crazy, but I find the sub-optimal “takes a lot of parameters” approach
to be more readable, maintainable, and junior dev-able. Don’t get me wrong, I
see why that’s not ideal, but currying just seems immensely more complicated
and harder to maintain, teach, etc... of course I’ve voided any chance of
membership to the “clever programmer club” with this perspective, but I
stopped caring about that long ago.

~~~
fireflies_
Me too. I can't imagine trying to maintain a project written like this so I'd
still consider you a member of the "clever programmer club" in good standing.
Ideas like this make sense when the language gives you good support for them
like Haskell does:

[https://www.haskell.org/tutorial/functions.html](https://www.haskell.org/tutorial/functions.html)

In languages like Go, you'll write much more "composable" software by sticking
to what the language gives you instead of trying to force this in.

~~~
karmakaze
I remember working in a Go codebase and that was littered with functions that
take functions returning funtions that take functions, etc. I couldn't imagine
what compelled them to write this way. Now I can see that they just realized
first-class functions, dependency injection, and maybe an article about
currying. There was almost no way to follow the problem decomposition nor
execution path as each aspect rather than being dealt with as encountered just
got pushed into a more and more complicated function that eventually executed
everything when given the input, an http request!

~~~
weberc2
You see this a lot with HTTP requests. People realize they're often writing
the same code over and over and so they pull it out into a middleware of some
kind. It's trading off a little readability in exchange for DRYness.

------
gizzlon
You can do this, but should you?

Solutions like this, more abstraction to avoid repetitive code, are usually
much worse than the problem.

> _Though we notice we only greet for mornings and afternoons so always having
> to pass “Good morning” or “Good afternoon” becomes a bit annoying._

Maybe? But one can do much much much worse than "a bit annoying"

> _It would be great if we could create an instance of our “greet” function
> with the first argument pinned down._

No.

~~~
iikoolpp
Ah yes, the Go mantra. Make your code as dumb and long as possible.

~~~
dgb23
Writing dumb code is often a good thing. Dumb code still solves your problem
and can be structured well to keep it readable and maintainable.

I feel like code even should be dumb most of the time and only clever when
needed. The hard part is to figure out when to be clever.

~~~
qt-lmao
Write clever code then dumb it down

------
kazinator
> _Though we notice we only greet for mornings and afternoons so always having
> to pass “Good morning” or “Good afternoon” becomes a bit annoying._

There are solutions for this specific example not involving currying, like
making a simple convenience wrapper:

    
    
      func greet(greeting, name string) string {
        return fmt.Sprintf("%v %v", greeting, name)
      }
    
      func goodMorning(name string) string {
         return greet("Good Morning", name)
      }
    

Or just binding "Good morning" to a variable like _gm_ and using that in
repeated calls to greet: greet(gm, "This Person"); greet(gm, "That Person").
That is still reasonably ergonomic, and avoids repeating the greeting string.

~~~
kitd
The point is about composability of functions though. Your example does it
statically. Currying and partial application allows it to be done dynamically
within the running program.

~~~
kazinator
Actually my example is based on partial application involving anonymous
functions. It's just hand compiled.

I manually lifted the lambda to the top level, and de-anonymized it with a
name. Then I realized that the only captured parameter had a binding to a
string literal "Good Morning", so I propagated that literal into the closure
body, eliminating the variable, and that variable's environment.

It ended up looking static due to the static literal, basically.

------
H1Supreme
I usually create a struct once my parameter list goes past 3. Then, pass that
in. Or, if applicable, create a method instead.

~~~
Insanity
In production code I do this too. The struct approach has various advantages
(nice syntax, maintainable, shows the meaning of what you are passing, ..).

I like functional programming hence the blogpost, and I like that I can do
this in Go. There are places where you might want to do this but I'm not going
to advocate doing this _every chance you get_.

But hey, Go lets me write how I want and that's pretty cool!

------
vips7L
In Java we would use `String.format`.

[https://docs.oracle.com/javase/8/docs/api/java/lang/String.h...](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#format-
java.lang.String-java.lang.Object...-)

~~~
cozos
String.format is slow compared to normal string concatenation (i.e. "foo" \+
"bar")! Bit me once when using String.format in a hot path.

[https://stackoverflow.com/questions/513600/should-i-use-
java...](https://stackoverflow.com/questions/513600/should-i-use-javas-string-
format-if-performance-is-important)

~~~
vips7L
Those benchmarks can't be accurate as they don't use JMH.

Edit: i do believe you that + is faster, as it doesn't need to parse the
format string, but you should still always do benchmarks with JMH or they
won't be accurate.

------
eximius
I mean, is this even currying? Or just emulating currying?

Without it being done automatically, it is an ergonomic loss, readability
loss, etc.

~~~
contravariant
Don't confuse special syntax with the concept itself. Currying is merely an
equivalence between functions of 2 parameters to functions of 1 parameters
that return functions. Doing it explicitly is still currying all the same.

------
wgx
Off-topic: I see 'medium.com' and I don't tap because I can't face the pop-ups
and nag modal. Sad to think, at one time Medium used to be the cleanest
reading experience.

~~~
minxomat
I usually hate these kinds of comments but I have to: Please check out dev.to.
It's a minimal, fast, developer focussed blogging platform. It's open source,
and quite active.

~~~
iikoolpp
In 3 months time: Off-topic: I see 'dev.to' and I don't tap because I can't
face the pop-ups and nag modal. Sad to think, at one time Medium used to be
the cleanest reading experience.

