This seems like a super interesting article and I’m currently digging into it. At the outset, it isn’t clear to me why there is a space between the name of the function and its arguments.
The article says “Functions are called with a space between the name and parenthesis. This is done to simulate calling functions by juxtaposition, and it’s helpful for calling curried functions.” but that doesn’t actually help me understand anything. What does “calling functions by juxtapostiion” mean, and why is the space helpful for calling curried functions?
Hey, glad you find it interesting. The space isn’t required, and you could call it without a space there, but in languages like Haskell where currying is more common than JavaScript, functions are called by “juxtaposition”, where arguments are separated by a space. In JavaScript, calling a function requires parenthesis, and calling curried functions would look like f(x)(y)(z)
. I added that note there just to clarify the notation because it’s not common to call functions this way, but I think f (x) (y) (z)
looks nicer.
I’ll edit it to make it clear that it’s not required and purely there for aesthetic purposes, thank you!
It’s not much. In some math texts it is common to write “f x” instead of “f(x)” - that is the juxtaposition which means just “put things next to each other”. That notation is nice, less typing and easy to read, except when there are multiple arguments and function valued expression or other forms of ambiguity. Does f x g y mean f(x,g,y) or f(x)(g (y)) or some other variant. “Currying” just means packing multiple arguments into one as a form of notational simplicity. e.g. f(x,y,z) is f(q) where we’ve done something to stuff x,yz into q or into f itself so add(a,b,c) could be add’(c) where add’(x) = add(a,b,x) or something. Seems pointless in this case.
If you can’t do
int x;
x = f(0);
x = g(x);
because your programming language does not have variable assignment, you need to do either
g(f(0))
which can become too awkward with complex formulas
or have a fancy ;
so f(0) ;; g(_)
means “I will avert my eyes while the compiler does an assignment to a temp variable and pretend it didn’t happen”
“Currying” just means packing multiple arguments into one as a form of notational simplicity
I don’t think that is accurate. Currying is about transforming functions that get multiple parameters into a sequence of functions, each of which takes one argument.
That is still a somewhat imprecise description, but I think an example would be more clarifying than going deeper into the theoretical details: If we take sum as non-curried function, it takes two integers to produce another one, the type is something like (Int x Int) -> Int
, and in practice you call it like sum(1, 2)
which evaluates to 3.
The curried version would be one function that given an integer a
returned a function that given an integer b
returned a+b
. That is, sum is transformed into the type Int -> (Int -> Int)
. Now to calculate 1 + 2 we should first apply sum to get a function that sums one, like sum1 = sum(1)
, where sum1
is a function with type Int -> Int
; and then apply this new sum1
function to 2, as in sum1(2)
which returns 3. Or in short, dropping the temporary variable sum1
, we can apply sum(1)
directly as in (sum(1))(2)
, and get our shiny 3 as result.
If your language uses space to denote function application, then you can write that last application as (sum 1) 2
. Finally, if application is left associative, you can drop the parenthesis and get to sum 1 2
, which, is arguably, pleasant syntax.
because your programming language does not have variable assignment
Just use a different variable as you should in the first case as well and it works just fine.
let x = f 0
y = f x
in ?somethingWithY
Also that’s a bad explanation of currying.
I will avert my eyes while the compiler does an assignment to a temp variable and pretend it didn’t happen
You have a negative reaction to FP for some reason which leads you to write these cheap jabs that are misinformative.
I have a negative attitude to mystification. I don’t like it when reasonably simple programming techniques are claimed to be deep mysterious mathematical operations. Your example, is, of course, an example of why these “fancy semicolons” are needed when it is scaled up. Imagine how hard it would be to track a state variable, say an IO file descriptor around a program if we had to do fd_1, fd_2, fd_n every time there was an i/o operation - keeping these in order would be painful. The “combinator” automates the bookeeping.
The explanation of Currying is perfectly correct, I think, but I’d like to hear what you think I got wrong. There’s not much to it.
In much of mathematics, all of this is just a notational convention, not a endofunctor on a category of sets. The author, who is at least trying to make things clear, could have simply written:
The notation is simpler if we write “f x” to indicate function composition instead of “f(x)”, otherwise it gets cluttered with parenthesis. To avoid ambiguity with multiple arguments, only single argument functions are allowed and we take care of multiple arguments by using functions that produce functions as values so, instead of f(x,y,z) the value of f1 x is a map f2 and f2 y produces a value f3 and f3 z then is equal to f(x,y,z). Equivalently, f(x,y,z) = ((f1 x) y) z.
I think FP is an interesting approach. I wish it could be treated as a programming style instead of as Category and Lambda Calculus Notational Tricks To Impress your Colleagues.
Functions take only one argument. So it’s really taking a (x * y * z), or an ‘x’ and a ‘y’ and a ‘z’. Currying is taking a function that takes an (x * y * z) -> w and transforms it to (x -> (y -> (z -> w))) aka (x -> y -> z -> w) this is useful because it allows us to create little function generators by simply failing to provide all the arguments. This isn’t simply a notation difference though because they are completely different types and this can matter quite a bit in practice. While yes there is a one to one correspondence between the two, that’s not the same as a “notational difference”. Tuples are fundamentally different objects than functions that return functions and this difference matters on a practical level when you go to implement and use them. You can say that it’s simply a notational difference but it’s untrue, and implicit conversions from one to the other does not mean they are “the same thing”.
In Haskell functions may take only one argument. In mathematics and in programming languages, it depends.
https://math.stackexchange.com/questions/2394559/do-functions-really-always-take-only-one-argument
In essence, it doesn’t depend. The notation depends but the notation represents one thing. f(x,y,z,w) is an implicit tuple of x,y,z,w. Without this there’s no concept of like domain of a function. This is all philosophical waxing but once you talk about currying it starts to matter because it affects what things are possible because not all arguments are provided at once. You could argue that objects and mutability sidestep this but I’d also argue that mutation within a function begins to deviate from a well defined “mathematical” function. That may be fine for you, and that’s okay. However since this conversation is primarily about definitions and we talked specifically about the mathematical way of modeling programming with functions yknow it matters.
For example in javascript the difference between f(x)(y)(z) and f(x,y,z) is literally different computations, and while there are times you can convert between the two freely, there are things that f(x)(y)(z) can do that f(x,y,z) cannot. For example I can use f(x)(y), to create a callback to defer computation with because f(x)(y) returns a function which takes a “z”. That’s genuinely useful. Now you can meaningfully argue that with objects you can do the same thing and that’s great but this is about functions and function passing. So it is actually meaningful to describe what you can and cannot do with these things.
This is all philosophical waxing but once you talk about currying it starts to matter because it affects what things are possible because not all arguments are provided at once. You could argue that objects and mutability sidestep this but I’d also argue that mutation within a function begins to deviate from a well defined “mathematical” function.
Very little in programming is a mathematical function. Even something like (==) : a -> a -> bool
isn’t a function, as its domain would be the universal set.
Also, I don’t think all mathematical functions are curryable? Like consider the function f[x: R^n] = n
, which returns the number of arguments passed in. I don’t think there’s a way to curry that.
A year or two ago I wrote an Idris function that took an arbitrary number of (curried) arguments and put them in a list (and gave you the argument count). From what I remember it used a type class with one instance for (->)
(the accumulator) and one for the result type, and a lot of type inference. I’ll dig it out later.
Edit: That was an already-curried function. You could potentially automatically curry f[x: R^n]
using the same technique since, in Idris, tuples are constructed like lists: (1, 2, 3)
is the same as (1, (2, (3, ())))
, so you could deconstruct a cartesian product while simultaneously producing a chain of (->)
function constructors.
Both of these points while interesting, and I think important questions to ask, don’t affect the position that currying is not simply a notational difference.
In essence, of course it depends, but it’s trivia. The course notes for the mulivariate calc course at MIT begins “Goal of multivariable calculus: tools to handle problems with several parameters – functions of several variables.” I’m amazed that some Haskellian or Curry Fan has not intervened to correct the poor fool teaching that course all wrong - “Excuse me, but those are not multiple variables, they are vectors! Please write it down.” If you did say that, and the Professor was in a good mood, she’d probably say: yes, that’s another way to look at the same thing.” And if you then insisted that “a well defined mathematical function” has a single variable, well … As usual, the problem here is that some trivial convention of the Haskell approach is being marketed as the one true “mathematics”.
I have no idea what a “mutation within a function” would mean in mathematics. Programs don’t have mathematical functions, they have subroutines that may implement mathematical functions. There is no such thing as a callback in the usual mathematical definition of a function. Obviously, within a programming language, there will be differences between partial computation or specialization of a function and functions on lists. You seem to be mixing up what programming operations are possible on subroutine definition with the mathematical definition of a function - unless I’ve totally missed your point. Obviously, for programs there is a big difference between a vector and a specialized function. But so what?
You have confused operads with categories, I think.
You can be upset about it, but currying isn’t simply a notational difference from multivariate functions.
Reminds me a bit of intercooler, which I’ve always admired.
yes, I really liked the idea of intercooler when it came out, never used it though.
I’m sure this can be easily implemented in stimulus though (with a stimulus-friendly syntax)
I host all my static nonsense on Gitlab Pages, and its CI is more than enough for what I need to do with it. One simple git push
and minutes later, I’m good to go.
I’m currently using Pollen. It is pretty neat :) https://docs.racket-lang.org/pollen/ It’s intended for books, but I could see it easily being used for writing and publishing blogs, like this one: https://thelocalyarn.com/excursus/secretary/
I started by working at startups as a designer. I did basic front-end (html, css, light javascript) for years until I discovered Backbone at a company I was at, which was a revelation to me at the time. From there, I discovered React and decided I didn’t want to do anything else. So I found a startup willing to hire me as a front-end engineer and here I am, a few jobs later, a senior-ish FE dev. It seems to be pretty easy to find work (even as a junior dev) in the SF Bay Area, fwiw.
Agreed. Property is theft!
Location might be an issue, since not all of us are in the Bay Area. Perhaps simultaneous local meetups connected by video call would work.
Gordon R. Dickson wrote a sci-fi book, published in 1984, called The Final Encyclopedia. It was all knowledge in the world with an AI to search.
I wanted this in real life. Xanadu seems like Ted Nelson wanted it too. Wikipedia is an organized crowd source. The WWW probably contains all the knowledge but you need a search and organization scheme to extract the encyclopedia from the noise.
“All the knowledge” in a single container might be possible but it will be hard for people to interact with due to their biases. Wikipedia is a good example of this as it lays bare the difficulty people have with accepting different views - contentious subjects tend to be colonised by a given faction which does its best to eradicate any and all data which negates their position. While it might be theoretically possible to create an AI which can serve as a data steward making sure all points of view are taken into account, it is hard to see how such a machine could survive the wrath of the censor.
I think this view is understandable but naïve, and I can prove it by saying that you are educated stupid for not accepting the four-corner cubic world which wisest human Gene Ray tried to reveal to the world despite the cubeless academia attempting to shut him up at every turn, because all academia is oath-bound to deny cubic reality and preach the Greenwich Fallacy.
Or are you an agent of the Gangster Machine, as revealed by Francis E. Dec? Or are you an X-Soviet Armenian whose grandparents are guilty of genocide against Turks? Hard to tell. With any luck, however, you’ve picked up the thread: Some points of view are not cogent, not rational, and not connected to reality. They only deserve mention in listings of “crazy stuff some people apparently believe” which, no matter how diplomatically you title it, is a category which is always going to be inherently insulting. You have to figure out what a “point of view” is, when it comes to getting all of them represented in an article about some real-world subject, and that kind of bootstrapping problem is an inherent bias in any encyclopedia project.
You’re talking fiction, I’m talking facts. The “four-corner cubic world” and the “agent of the Gangster Machine” and more of such are provably false and can be written down as such. Other areas are not so clear and should be open for discussion, a good example here is the issue of climate change. There is a lot of science on this subject which can be used to push a number of views, from “climate change has always occurred and is a natural phenomenon which is unrelated to human activities” to “anthropogenic climate change is boiling the planet”. Have a look at Wikipedia, especially at the discussion pages for subjects related to this issue to see which faction has taken over this area.
I guarantee you that some of the things you consider facts are obviously fiction to others, and vice-versa.
Some people feel the same way about the existence of trans people.
Wrong. Aside from the fact your first “quote” is unrelated to the second, the fact is that AGW is very well-demonstrated and accepted by all serious scientists in the field. The “debate” is funded by people who have some kind of interest in seeing people doubt things we know quite well.
This is because NPOV is biased towards the scientific consensus, as it should be.