Live data from Hacker News

Swift and the Legacy of Functional Programming

realm.io

61–70 of 188 posts

Re: Swift and the Legacy of Functional Programming

#61

Earlier quoted context omitted.

Haskell's syntax isn't actually that complicated. There are some common functions with operator names that can be hard to read if you're not used to them, but those are library defined. The syntax itself is actually fairly simple. And incidentally, this would probably be something like (EDIT: made example more realistic): filter personIsValid (map initPerson names) in Haskell. Which looks much cleaner than the lisp t…

That's because your code assumes those convenience functions exist while the parent's code writes out the anonymous functions. The direct translation of yours' to Clojure would be: (filter valid-person? (map init-person names)) Meanwhile, the direct Haskell translation of the parent comment is: filter (\p -> isValid p) (map (\n -> Person n) names)

[deleted]

Re: Swift and the Legacy of Functional Programming

#62

Earlier quoted context omitted.

I think if the second one is easier, you've more or less been taught to think like a microprocessor. That happens to most of us after a few years of writing imperative code. The more abstract functional approach is, however, conceptually simpler and more powerful at the same time. (For example, the first one is completely open to being performed in parallel.) With a little experience, functional programming is quite…

I can't help thinking like a microprocessor. Even when mixing functional style into my code, my brain tries to get a grasp on how it's going to be processed. So the first example looks to me like two loops (hopefully the compiler does a better job on that), while the second one is obviously one loop. I am already trying to guess how a compiler would parallelize that...

The second one might be obviously a single loop, but it is not obvious that it is O(n) and depends on the implementation of "append". It also tells you nothing about how the memory gets accessed and I'm assuming here that the for loop works just as well over linked lists and over arrays. In other words your knowledge that this is a single loop can be very misleading when thinking of expected performance. Which is fine because we work with abstractions such that we don't have to think about such details all the time, because that's not doable.

The first example is simply more abstract. It might be a single loop in case the implementation is lazy, it might be two loops in case it is strict. However, look closer. Those filter and map operations can be applied to basically anything you want, including asynchronous / infinite streams.

Your second loop on the other hand would have a hard time being translated to anything else than something that works on finite lists and that builds a finite buffer and not doing anything else while doing this.

Or in other words, your knowledge about this manual loop is not transferable ;-)

Re: Swift and the Legacy of Functional Programming

#63

Earlier quoted context omitted.

Haskell's syntax isn't actually that complicated. There are some common functions with operator names that can be hard to read if you're not used to them, but those are library defined. The syntax itself is actually fairly simple. And incidentally, this would probably be something like (EDIT: made example more realistic): filter personIsValid (map initPerson names) in Haskell. Which looks much cleaner than the lisp t…

That's because your code assumes those convenience functions exist while the parent's code writes out the anonymous functions. The direct translation of yours' to Clojure would be: (filter valid-person? (map init-person names)) Meanwhile, the direct Haskell translation of the parent comment is: filter (\p -> isValid p) (map (\n -> Person n) names)

Huh? No, anyone who writes it in Haskell would not use those lambda abstractions. You would just use "filter isValid (map Person names)".

Re: Swift and the Legacy of Functional Programming

#64
post #63

Earlier quoted context omitted.

That's because your code assumes those convenience functions exist while the parent's code writes out the anonymous functions. The direct translation of yours' to Clojure would be: (filter valid-person? (map init-person names)) Meanwhile, the direct Haskell translation of the parent comment is: filter (\p -> isValid p) (map (\n -> Person n) names)

Huh? No, anyone who writes it in Haskell would not use those lambda abstractions. You would just use "filter isValid (map Person names)".

I'm assuming Person is a record constructor, is isValid here a field in that record or another function?

Re: Swift and the Legacy of Functional Programming

#65

Earlier quoted context omitted.

Haskell's syntax isn't actually that complicated. There are some common functions with operator names that can be hard to read if you're not used to them, but those are library defined. The syntax itself is actually fairly simple. And incidentally, this would probably be something like (EDIT: made example more realistic): filter personIsValid (map initPerson names) in Haskell. Which looks much cleaner than the lisp t…

That's because your code assumes those convenience functions exist while the parent's code writes out the anonymous functions. The direct translation of yours' to Clojure would be: (filter valid-person? (map init-person names)) Meanwhile, the direct Haskell translation of the parent comment is: filter (\p -> isValid p) (map (\n -> Person n) names)

No one would ever write the latter, because (\p -> isValid p) is equivalent to isValid.

However you're right that the function names would probably be a little longer in practice, and I've edited my example to reflect that. (But they're not convenience functions, they just have longer names due to Haskell's more limited namespacing)

Re: Swift and the Legacy of Functional Programming

#66

Earlier quoted context omitted.

For me the problem with Haskel (and, by extension, Swift) is the syntax is very complicated. The example above is better taught through a functional language that has almost no syntax like a Lisp. (filter (fn[p] (p :valid?)) (map (fn[n] (Person n) names))

Haskell's syntax isn't actually that complicated. There are some common functions with operator names that can be hard to read if you're not used to them, but those are library defined. The syntax itself is actually fairly simple. And incidentally, this would probably be something like (EDIT: made example more realistic): filter personIsValid (map initPerson names) in Haskell. Which looks much cleaner than the lisp t…

Except in these two brief examples, Haskell employs syntactic sugar with hidden semantics that nobody but an acolyte would understand (periods and two kinds of brackets mean what?). At least the Lisp scoping here is explicit and employs minimal abstruse sugar.

I'll admit Lisp's myriad nesting of brackets is not ideal either. But surely there are more elegant and intuitive notations for functional scoping than is seen here.

Re: Swift and the Legacy of Functional Programming

#67

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.

No, but this shouldn't be taken as an indictment of FP general. I prefer

    persons = filter isValid (map init names)
to both. Swift just isn't really a functional language in any useful sense.

Re: Swift and the Legacy of Functional Programming

#68

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.

I find the first one to be far easier to read. You can basically just read it from top to bottom and know exactly what it does. "Take names, turn each one into a Person, keep the ones that are valid."

The second one takes a lot more work. First, I have to read through the code and recognize that this is a loop that accumulates values into a new array. Then I have to pick it apart and see exactly where the accumulation takes place, and how that value is derived. It's not hard by any means, but the first one is far more straightforward.

Re: Swift and the Legacy of Functional Programming

#69
post #42

Ask five programmers to define functional programming, get fifteen different answers.

The term "functional programming" is overloaded, but I think there's a sensible way to split the term into two halves. "Purely functional programming" is writing programs to resemble mathematical functions, with referential transparency and absence of side-effects and so forth. Also know as "what Haskell does." "Function-oriented programming" is writing programs using functions as your main tool for abstraction, enca…

Actually, both of those families come from lambda calculus, except in different way. Lisp comes from untyped lambda calculus (and adds things like car, cdr and eq on top of it), while Haskell (and ML) comes primarily from typed lambda calculus.

I offer a definition of "functional programming" as "based on semantics of lambda calculus".

Re: Swift and the Legacy of Functional Programming

#70

Earlier quoted context omitted.

Haskell's syntax isn't actually that complicated. There are some common functions with operator names that can be hard to read if you're not used to them, but those are library defined. The syntax itself is actually fairly simple. And incidentally, this would probably be something like (EDIT: made example more realistic): filter personIsValid (map initPerson names) in Haskell. Which looks much cleaner than the lisp t…

Except in these two brief examples, Haskell employs syntactic sugar with hidden semantics that nobody but an acolyte would understand (periods and two kinds of brackets mean what?). At least the Lisp scoping here is explicit and employs minimal abstruse sugar. I'll admit Lisp's myriad nesting of brackets is not ideal either. But surely there are more elegant and intuitive notations for functional scoping than is seen…

I'm not sure what you're talking about? My example contains no periods and only one kind of brackets? Did you reply to the wrong post?

Admittedly, it might be written with $ in practice, but that's a fairly simple idiom, and I tend to avoid it.

Post reply on HN