Live data from Hacker News

Swift and the Legacy of Functional Programming

realm.io

141–150 of 188 posts

Re: Swift and the Legacy of Functional Programming

#141
post #80

Earlier quoted context omitted.

There's only one definition that matters: functional programming is programming with mathematical (pure) functions. As a consequence you get referential transparency and thus equational reasoning. But change this definition and the term becomes meaningless.

Though by this definition, Lisp, the granddaddy of functional programming languages, is not a functional programming language.

The original LISP was influenced by Alonzo Church's lambda calculus, see: https://dl.acm.org/citation.cfm?id=367199 - however if you'll study its history the first Lisps were only experiments and for example they didn't have lexical scoping, but dynamic scoping. The Lisp descendant that made FP doable was Scheme, bringing lexical scoping and call/cc.

And today's Common Lisp is definitely not Scheme, or an FP language. You can do FP in CLisp of course, since it's quite capable, but CLisp is a general purpose language and is used as such. And in my small experience from playing with it, there isn't much FP in CLisp, but YMMV.

Lisp in general is a big family. Emacs Lisp for example has absolutely nothing to do with FP.

Of course you can romanticize about Lisp and it definitely has some cool descendants like Clojure, but you know, don't do it too much :-)

Re: Swift and the Legacy of Functional Programming

#142

Earlier quoted context omitted.

It indeed isn't. Here's my litmus test. Is 2^100 always equal to 2^100? Let's ask SBCL: * (eq (expt 2 100) (expt 2 100)) NIL Damn object identities, ruining muh equalities. (Disclaimer: I'm not saying functional programming is the right approach for writing every program, but if a language can't even get arithmetic and relational operators right...)

I don't see how support for multiple equalities makes something not a functional language. Functional doesn't mean "the semantics of everything is tied to its printed syntax" so that if two things look the same in the syntax, they denote the same thing. (Right?) Suppose we take Haskell and give it an equal operator which can tell that two bignums are different instances and not equal. Does it cease being functional?…

> Functional doesn't mean "the semantics of everything is tied to its printed syntax" so that if two things look the same in the syntax, they denote the same thing. (Right?)

I don't care about syntax. I want to manipulate the values I care about, not object identities. I want to operate on numbers, strings, lists, trees, what have you. Not memory cells that allegedly contain representations of numbers, strings, lists, trees, what have you. This is strictly a semantic issue.

> I don't see how support for multiple equalities makes something not a functional language.

FWIW, what most languages call “physical” or “reference equality” is a special case of structural equality (which is always the prior notion). Structural equality of mutable cells (which have dedicated types in Haskell and ML) happens to be physical equality.

> Suppose we take Haskell and give it an equal operator which can tell that two bignums are different instances and not equal. Does it cease being functional?

Yes.

> What if we don't use that operator anywhere in a program and don't even know it exists; how do we know the language is not functional?

Then you're doing functional programming in a non-functional language.

Re: Swift and the Legacy of Functional Programming

#143
post #139

Earlier quoted context omitted.

Your " function-oriented programming " has an older and more suitable term: https://en.wikipedia.org/wiki/Procedural_programming You see, if a function isn't pure , then it isn't a (mathematical) function. But we tend to overload terms because of their marketability. In the same way that some companies wanted to overload " open source ". The general rule of thumb is that if something is desirable by the market, then…

Procedural programming usually does not include the use of higher-order functions, and "function-oriented" here seems proper for Lisp and some styles of Python, with their heavy use of filter/map/apply/parallel-map-reduce etc.

In mathematics a function is a mapping having the property that each input is related to exactly one output. This brings with it certain properties you can rely on. In particular functions themselves are also values that can be passed around as parameters or returned by other functions, hence higher order functions.

It's regrettable that we overloaded the word "function", given we could have used procedures or subroutines to denote, you know, jumps in code that trigger effects and push/pop the call stack.

And as proof, applying filter/map and other similar operations with side-effecting procedures is a really, really bad idea, because such operators are usually implemented with lazy behavior (in order for "fusion" to happen) and laziness doesn't blend well with side effects, with the result becoming non-deterministic. E.g. at least people that worked with Map-Reduce frameworks should know what I'm talking about.

Or in other words, there is no such thing as "function-oriented", there's just local application of FP where it seems to be making sense, but with all the caveats that entails.

Re: Swift and the Legacy of Functional Programming

#144

Earlier quoted context omitted.

I don't see how support for multiple equalities makes something not a functional language. Functional doesn't mean "the semantics of everything is tied to its printed syntax" so that if two things look the same in the syntax, they denote the same thing. (Right?) Suppose we take Haskell and give it an equal operator which can tell that two bignums are different instances and not equal. Does it cease being functional?…

> Functional doesn't mean "the semantics of everything is tied to its printed syntax" so that if two things look the same in the syntax, they denote the same thing. (Right?) I don't care about syntax. I want to manipulate the values I care about, not object identities. I want to operate on numbers, strings, lists, trees, what have you. Not memory cells that allegedly contain representations of numbers, strings, lists…

[deleted]

Re: Swift and the Legacy of Functional Programming

#145

Earlier quoted context omitted.

I think the readability is a bit of a wash. But the second one is more debuggable than the first, which I think is even more important than readability. In the first case, you need to rewrite the control structure to even be able to inspect anything: let allPersons = names.map(Person.init) {log allPersons[0].name} {breakpoint} let persons = allPersons.filter { $0.isValid } There are lots of data structures in this st…

> But the second one is more debuggable than the first, which I think is even more important than readability. The first is less likely to require debugging in the first place. > There are lots of data structures in this style of programming that don't have any names. So you can only reason about things that have names? Now we know where idiomatic Java comes from. > Who knows what kind of data structures map and filt…

> So you can only reason about things that have names?

I think the point was that you can debug things that have names because they are separately watchable.

But apart from that breaking things down and naming them can make for easier comprehension. This is true in written English: Naming actors when explaining something and using an active voice is generally recommended. e.g "The user enters a password and the program encrypts it and stores it in the database" Rather than: "Passwords will be stored encrypted"

But also in mathematics. When working something out it's better to name intermediate values (x,y) and then use them in new equations rather than use the equivalent of a point free style that you sometimes see in functional programs.

Re: Swift and the Legacy of Functional Programming

#146
post #94

Earlier quoted context omitted.

In this case, it's unfortunate that there's no, "will this name create a valid person object?" predicate. much much better to filter the names, then make the objects. In this case, as long as append is O(1), i think the imperative version has a big benefit, it avoids building the name size list of persons. If you've got a billion names and 2 valid person objects, the imperative version is a big win. Of course that pr…

Most languages implement map and filter in terms of lazy sequences so they would not allocate an intermediate list (Scala is an exception but I believe you can request laziness).

> so they would not allocate an intermediate list

Not quite. Lazy sequences make it so that thinking about fusion/deforestation makes sense. This is an optimization the compiler can make. Naively, you still end up with as many allocations as before (just in a different order).

In Haskell, this sort of optimization is actually user-customizable using REWRITE RULES. And you get it for lists out of the box.

Re: Swift and the Legacy of Functional Programming

#147

I'm curious, does every else find this let persons = names .map(Person.init) .filter { $0.isValid } easier to read than this? var persons: [Person] = [] for name in names { let person = Person(name: name) if person.isValid { persons.append(person) } } I understand and appreciate the value of compact code, but I find the first one harder to read. A lot of inferred/token based coding is harder for me to mentally parse.

In Python, the only good language, this could be expressed as: [person for person in (Person(name) for name in names) if person.isValid()] or: filter(lambda p: p.isValid, map(Person, names)) or: persons = [] for name in names: person = Person(name) if person.isValid(): persons.append(person)

So much for "There's Only One Way To Do It". :)

Re: Swift and the Legacy of Functional Programming

#148
post #133

Earlier quoted context omitted.

Structural equivalence is given by EQUALP and has of course its own limitations (but works with trees, user-defined structs and hash-tables, for example). Of course, if you use the identity comparison, you get different results. I agree CL does not fit your definition of functional programming. An implementation is permitted to make "copies" of characters and numbers at any time. The effect is that Common Lisp makes…

I'm aware of EQUALP. But the problem remains that it's possible to distinguish between supposedly “equal” values. Lisp and Scala are first and foremost object-oriented languages - whatever values you want to manipulate are always subordinate to objects whose physical identity in memory matters in the language's semantics, no matter how irrelevant they might be for your problem domain. On the other hand, in Haskell an…

I am also aware of that. I am not really trying to convince you of anything, mostly trying to prevent casual readers from being taught Common Lisp from you. Look at the example you just gave, this is beyond ridiculous. I would prefer if you were focusing on what you want to fight "for", not what you want to fight "against".

You like having a strong separation between the language and its implementation. I get it. Note however that if you are the Haskell compiler, you can know things the programmer cannot, or you can inject code that can perform manipulations the programmer cannot express. There probably is an identity equality operator down there, that people cannot access. If you like that, I can understand; I can understand the appeal for a strict separation of concerns and the desire to express only the high-level intent. But really, I think this is not much different in CL and that you are focusing on implementation details. In CL the separation is not enforced, and that is your main problem with it.

The CL compiler is defined at the language specification level. You have access to internals, by choice, just as if you were writing Haskell ASTs using an Haskell compiler's internal API. As such, you can cross abstraction barriers whenever you need. We already discussed about this once, you can use purely functional data-structures (see FSET) and EQUALP and code to that functional interface and pretend there is no computer down there. Then, if you want, you can play with packages and symbols to make MAP & co. refer to the parallel version (see LPARALLEL), re-compile and have parallel code (this works best with unqualified symbols and different package definitions for the same file).

In all PL discussions, there is eventually mention of an hypothetical sufficiently smart compiler. The CL point of view is (among other things) that such a compiler is one where a programmer can easily add its own extensions. That allows you to express the intent of the program clearly in one place and have the implementation details elsewhere.

Re: Swift and the Legacy of Functional Programming

#149
post #3

Yo, would be nice to have some functional programming language with decent syntax to program apple machines. Let's call it Dylan to honor the most recent winner of the Nobel prize for literature. Just kidding. The bottomline of this page and talk is that Swift is still not functional. But you can do cool things with it.

I dunno; I think the bottom line of this page is that functional programming is a set of approaches for solving problems, and some of those approaches can be done in Swift.

My take was that you can solve problems by breaking things down. In functional programming you do so with functions. In Swift you can do so with types.

Re: Swift and the Legacy of Functional Programming

#150
post #44

Earlier quoted context omitted.

Take it from the other side: why would a language that allows to create higher-order functions/closures not be called functional?

Most languages only have higher-order procedures, not higher-order functions. As for closures, well, closures are an implementation technique . Not distinguishing between language features and implementation techniques is a part of an established tradition that comes from Lisp, but that doesn't make it any less wrong.

> Most languages only have higher-order procedures, not higher-order functions.

What do you mean by that?

Post reply on HN