Hacker News new | ask | show | jobs
by fulafel 439 days ago
This is discussing Common Lisp which is not even a mostly-functional language, and far from purely functional.
2 comments

He says Lisp, rather than Common Lisp. Sure, given the context he's writing in now, maybe he means Common Lisp, but Joe Marshall was a Lisp programmer before Common Lisp existed, so he may not mean Common Lisp specifically.
Somehow haskell and friends shifted the discussion around functional programming to pure vs non-pure! I am pretty sure it started with functions as first order objects as differentiator in schemes, lisps and ml family languages. Thus functional, but that's just a guess.
> Somehow haskell and friends shifted the discussion around functional programming to pure vs non-pure

In direct response every other language in the mid 2010s saying, "Look, we're functional too, we can pass functions to other functions, see?"

  foo.bar()
     .map(x => fireTheMissiles())
     .collect();
C's had that forever:

  void qsort(void *base, size_t nmemb, size_t size,
             int (*compar)(const void *, const void *))
In a way this is true.

A function pointer is already half way there. What it lacks is lexical environment capture.

And things that are possible to do with closures never stop amazing me.

Anyways, functional programming is not about purity. It is something that came from the academia, with 2 major language families: ML-likes and Lisp-likes, each focusing on certain key features.

And purity is not even the key feature of MLs in general.

Closures bring me joy.
They are one of those language features that, having learned them, it's a little hard to flip my brain around into the world I knew before I learned them.

If I think hard, I can sort of remember how I used to do things before I worked almost exclusively in languages that natively support closures ("Let's see... I create a state object, and it copies or retains reference to all the relevant variables... and for convenience I put my function pointer in there too usually... But I still need rules for disposing the state when I'm done with it..." It's so much nicer when the language handles all of that bookkeeping for you and auto-generates those state constructs).

Curiously, higher-order functions, and the concept of something like a closure, dates back to the earliest days of PL design - and I'm not even talking about Lisp! Algol-60, the granddaddy of pretty much every modern mainstream programming language, already had the notion of nested functions (which closed over variables from the surrounding scopes) and the ability to pass those functions to other functions.

They weren't fully first-class because there were no function-typed variables, nor could you return a function. Even so, this already lets you do stuff like map and filter. And Algol-60 programs from that era did use those capabilities, e.g.:

  PROCEDURE EULER (FCT, SUM, EPS, TIM)
   VALUE EPS, TIM;
   INTEGER TIM;
   REAL PROCEDURE FCT;
   REAL SUM, EPS;
  BEGIN
   INTEGER I, K, N, T;
   ARRAY M [0 .. 15];
   REAL MN, MP, DS;
   I := N := T := 0;
   M[0] := FCT(0);
   SUM := M[0] / 2;
  NEXTTERM:
   I := I+1; 
   MN := FCT(1);
   FOR K := 0 STEP 1 UNTIL N DO
   BEGIN
    MP := (MN + M[K]) / 2;
    M[K] := MN;
    MN := MP
   END;
   IF (ABS(MN) < ABS(M[N]) AND N < 15) THEN
   BEGIN
    DS := MN/2;
    N := N+1;
    M[N] := MN
   END
   ELSE
    DS := MN;
   SUM := SUM + DS;
   IF ABS(DS) < EPS THEN
    T := T + 1
   ELSE
    T := 0;
   IF T < TIM THEN
    GOTO NEXTTERM
  END;
No, functions aren't first class in C. When you use a function in an expression it undergoes lvalue conversion and "decays" to a pointer to the function. You can only call, store, etc function pointers, not functions. Function pointers are first class. Functions are not as you can't create them at runtime.

A functional programming language is one with first class functions.

What is the impact on the user of having first class functions vs first class function pointers?

Last I checked when you implement lambda in lisp it's also a pointer to the lambda internally.

Function pointers can’t close over variables.
The other important bit here is garbage collection.

Local and anonymous functions that capture lexical environments really, really work much better in languages built around GCs.

Without garbage collection a trivial closure (as in javascript or lisps) suddenly needs to make a lot of decisions around referencing data that can be either on the stack or in the heap.

That has nothing to do with the value/pointer distinction.

And “close over” semantics differ greatly depending on the language.