[HN Gopher] Building a new functional programming language
___________________________________________________________________
Building a new functional programming language
Author : signa11
Score : 79 points
Date : 2023-03-05 15:08 UTC (7 hours ago)
(HTM) web link (www.onebigfluke.com)
(TXT) w3m dump (www.onebigfluke.com)
| cde-v wrote:
| Seems like the correct answer here is that Brett Slatkin likes
| the smell of his own farts. Typical fart sniffer behavior.
| Max_Limelihood wrote:
| Because 14 wasn't enough. https://xkcd.com/927/
| juancn wrote:
| The problem is that those are f**king difficult problems to
| solve. Regardless of how you approach them. No tool or paradigm
| will make them easy, it may make a part of them easier (at some
| other cost somewhere else), but by no means will make it easy.
|
| Building large scale, low latency systems is really hard.
| Handling concurrency and shared state is hard.
|
| Heck, even functional programming is hard to grok for most
| people. The evidence is in its popularity (or lack of it).
|
| There's no large mystery why we all are not using functional
| programming exclusively: because it's hard. Imperative, with all
| it's drawbacks it's easier to grasp and closer to how hardware
| works. Most people find it more natural, there's no big
| conspiracy.
|
| But (there's always a "but"), the functional paradigm is
| essential to solve all those hard problems. It provides many
| tools where many common pitfalls are essentially avoided, but
| gaining a comfortable grasp of those tools takes work and it's
| not easy as many claim.
|
| They seem easy _after_ you 've had the "aha!" moment, but it's
| like advanced math, getting there takes time and a certain
| proclivity to it. Once you develop some sort of intuition, you
| tend to forget the effort it took to gain it.
|
| In any case, I love languages and new ideas, so I hope he
| succeeds (or fails in an interesting way where we learn something
| new).
| rurban wrote:
| He has set, not functional. See his Twitter
| bslatkin wrote:
| It's SSA. If you use (define) in Racket is it no longer
| functional?
| alexisread wrote:
| I'll drop this here: https://github.com/manuel/wat-js
|
| If you have delimited continuations then you can construct
| coroutines/threads/await/async, promises etc.
|
| I guess that this might be suitable for many scenarios thanks to
| nodejs, but the runtimes it relies on are not exactly small.
| PaulDavisThe1st wrote:
| I've been programming for 35 years or more, and I've yet to come
| across situations where the hard problem was _the language_.
|
| Sure, there are situations where I've been grateful for the
| ability to use Python (because everything is so easy), or Perl
| (because sometimes its the right tool for the job) or Lisp
| (because its slippery fluidity just feels right) rather than the
| C/C++ that I've generally used during that time.
|
| But the hard problems I've faced writing code would (almost?)
| never be made easier by using functional programming, or Rust, or
| Go or Swift or Brainfuck. The problems are hard because the
| problems are hard, and typically for me over the last 23+ years,
| it has been the combination of generically tough programming
| problems with performance requirements that ultimately make the
| choice of language mostly irrelevant.
|
| Sure, someone could offer me a thread-safe sparse integer-to-
| integer mapping container in another language, but then I have to
| wonder about what design assumptions were made and how performant
| it is, and if the language was clearly created to prevent me from
| ever doing such things myself, then I'm going to be deeply
| suspicious from the outset that it could possibly have my
| (coding) interests at heart.
|
| I understand that I'm not the typical programmer these days, and
| I don't work on entirely typical problems, but I can't help but
| feel that sometimes the focus on "languages to help programmers"
| comes from programmers who just don't enjoy their work enough
| and/or don't have enough to do.
| bslatkin wrote:
| I love to swing a hammer as much as the next programmer. But if
| you offer me a nail gun, even with slightly lower precision, I
| will happily use it the majority of the time and revert to my
| hand tools when it's most appropriate. This is about developing
| force multipliers and producing leverage, not avoiding the
| craft.
| PaulDavisThe1st wrote:
| I would say that a better analogy is that you've already got
| an experienced crew, some swinging hammers, some lugging nail
| guns and everyone's really quite good at what they do. But
| the plans from the architect are just _really hard to build_.
| You and the crew can do it, for sure, but the issues are not
| going to better or worse if the guys use the table saw to
| crosscut some of the framing elements or someone gets one of
| those new german tool widgets. I mean, sure, the tools might
| make a small difference to the process, but the overall
| experience will be dominated by the fact that the thing is
| just hard to build.
| not_the_fda wrote:
| I've also been doing this for over 30 years and agree with you
| 100%. Never has the language been the impediment, or the thing
| keeping me awake at night.
|
| We don't need more programming languages. All languages are
| either hated or not used. The language isn't the problem and it
| a poor craftsman that always blames the tool.
|
| I've never been on a retrospective of a failed project and the
| reason being the language.
| anonuser123456 wrote:
| As a developer I would agree. As a maintainer I would disagree.
|
| Some problems require paradigms to solve, and developing
| bespoke implementations makes maintenance extremely painful.
| sakras wrote:
| I definitely agree. I think somewhere along the way we went
| from solving problems to bickering about _how_ to solve
| problems. I feel there are now plenty of languages now that
| exist purely for aesthetic reasons (C++, Swift, etc) rather
| than having some deep technical reason for existing (C, Rust).
|
| I guess I get it though, designing your own language is great
| fun and I've definitely made a couple myself in my spare time.
| Chris_Newton wrote:
| _I 've been programming for 35 years or more, and I've yet to
| come across situations where the hard problem was_ the
| language.
|
| The hardest problem is usually something else, but IME some
| languages make it much easier to solve a given hard problem
| than others. Some languages are qualitatively safer. Some
| languages are much more expressive, in the sense that I can
| implement my solution with far less code/time/cost without
| compromising anywhere else.
|
| There is a difference between whether I can solve a problem and
| how efficiently and pleasantly I can solve a problem. I find
| choice of language rarely affects the former but often
| profoundly affects the latter.
| PaulDavisThe1st wrote:
| 100%. But that's why I mentioned performance. I work with
| realtime audio, and this puts most of the "pleasantly solve
| the problem" options off the table.
| iLoveOncall wrote:
| As always for those niche languages, if the answer is not
| personal entertainment, then the reality is that it's just poor
| judgement.
| century19 wrote:
| I'm surprised he doesn't mention Scala and Spark.
| bslatkin wrote:
| I think Spark is a good example of where the functional
| paradigm has done well in a niche.
| karmakurtisaani wrote:
| > The hypothesis I aim to test with a new programming language
| is: By making different tradeoffs, these issues can be mitigated
| and a more broadly-appealing functional language can be built.
| With such a language, I hope that the true promise of functional
| programming for parallel computing can be widely realized.
|
| Proceeds to give zero indication how to achieve this.
| karmakaze wrote:
| Very disappointed by the non-announcement. If it were a corp,
| it would be FUD.
|
| I'm curious as to what these different trade-offs are.
|
| > My conclusion is that there are major, well-justified reasons
| for why people strongly dislike functional languages.
|
| My conclusion is because most everyone is taught to think
| empirically and 'play computer' that functional doesn't fit in
| their preconceived brains. I once had someone say SQL didn't
| make sense because it's SELECTing fields (i.e. vars) before
| they're defined/assigned later in the (binding) expressions.
|
| People having trouble with FP is like how people who learn
| databases using ORM's don't deal well with SQL as expressions
| of set operations.
|
| There are varying limits to how much people like and handle
| abstract constructs before applying the construction to the
| data at hand but you can do a whole lot of effective and
| unsurprising development before getting to such esoteric
| levels.
|
| Edit: I was super-excited to open the link, and now on re-
| reading expect this new FP language to be as much an
| advancement as Go was to 'systems' programming. I hope I'm
| mistaken. Also odd that only Haskell and Lisp were mentioned
| when there are so many others. On the plus-side if Google were
| to make F# and back it as well as they have Go, that would be a
| win-win.
| lolinder wrote:
| > it would be FUD
|
| I thought FUD stood for Fear Uncertainty Doubt--it's usually
| used to indicate that something is designed to sow fear for
| clicks or for some ulterior motive, not for insubstantial
| non-announcements.
|
| Did something in this post evoke fear?
| karmakaze wrote:
| The point of FUD is usually to carve out a space where
| existing products/solutions can't compete with idealized
| vapourware. I updated my opinion to NIH (though could be
| both)--and still hope to be mistaken.
| karmakaze wrote:
| After reading their other post "The case for dynamic,
| functional programming", I would classify this as FUD, or
| rather NIH. Go got support by being touted as "Not Java". I
| can't say that this would gain much by being declared as "Not
| Elixir".
| jalk wrote:
| > My conclusion is that there are major, well-justified reasons
| for why people strongly dislike functional languages.
|
| I'm sure there are a multitude of different reason and likely
| require different conflicting tradeoffs to address
| bslatkin wrote:
| It's true and that is one of the largest challenges.
| Producing something that feels familiar (but not error prone)
| has been the way I've solved such conflicts so far.
| lolinder wrote:
| It's a four paragraph blog post answering the question "why?".
| I'm not sure why you expect him to delve into the how at this
| stage: he probably doesn't have anything fully formed yet.
| bslatkin wrote:
| Thanks! Right now the language's codebase is about 50KLOC.
| There's an interpreter for fast iteration and a compiler
| built on LLVM for producing native binaries. I'd like to make
| more progress on the parallel computing functionality before
| sharing it more widely.
| iampims wrote:
| https://twitter.com/haxor/status/1582878447134572544?s=20
|
| Looks like the syntax is taking shape at least.
| noelwelsh wrote:
| No language syntax needs return in 2023.
| bslatkin wrote:
| How should an early return if statement work instead?
| noelwelsh wrote:
| When if is an expression early returns aren't really a
| problem.
| bslatkin wrote:
| I understand what you mean. But I expect most potential
| users want explicit returns because they're familiar and
| more approachable for beginners.
| noelwelsh wrote:
| I disagree. You make two claims: familiarity, and
| beginner friendliness.
|
| For the first, I think it's a mistake to perpetuate the
| mistakes of the past. I don't think JS developers have
| had problems adjusting to the lack of return in arrow
| functions.
|
| Beginners have no preconceived notions of how a
| programming language should operate, and return makes the
| language model more complex.
|
| 1 + 1 evaluates to 2, but (in a language that requires
| return)
|
| def foo = 1 + 1
|
| foo
|
| doesn't for no good reason. This breaks the simple
| substitution model of evaluation.
|
| These claims could be addressed emperically, but I guess
| neither of us are going to do the research. :-)
| tsegratis wrote:
| He's going for apple/iphone style of drip feed product
| announcements to build excitement
|
| Look at us salivating for his big unveil -- we've probably
| already written more than he did
| User23 wrote:
| It basically comes down to nondeterminism. Pure functional
| languages supposedly make it easier to exploit associativity,
| commutativity, and distributivity to allow many expressions to
| have nondeterministic semantics that are amenable to concurrent
| execution. Argument evaluation also can be specified
| nondeterministic so the runtime is free to execute something
| like the following with two or more CPU threads:
| f(g(), h())
|
| Of course a well designed imperative language could also avoid
| overspecifying deterministic semantics and open itself up to
| similar optimizations, but for various reasons that hasn't
| caught on. One example would be specifying the conditional to
| select a branch with a true guard nondeterministically rather
| than deterministically in the order of appearance in the
| program text. Dijkstra's EWDs give many practical examples of
| why one might want such a thing.
|
| Another example would be deducing when statement composition is
| symmetric and allowing nondeterminism when it is. For example
| if f and g don't have access to each other's data then the
| following can be executed in two threads even with mutation:
| f(); g()
|
| Side effects will appear nondeterministically though which may
| or may not be a problem. As always an algorithm needs to be
| designed for the semantics the language has not those the
| programmer wishes it does.
| alexisread wrote:
| This makes a good case for effect systems in conjunction with
| FP, so they can be reasoned about as well. Something like
| https://koka-lang.github.io/koka/doc/index.html
|
| Having said that, having something like Daedelus in there as
| well would give a handle on temporal-based determinism, and
| then some allowance for delimited continuations would top
| things off nicely.
| worksonmine wrote:
| In his defense the title is "why" not "how". I guess you'll
| have to spend some sleepless nights waiting for the follow-up.
| bslatkin wrote:
| I'm sorry to make you wait.
| evanwang0 wrote:
| While certainly true that functional programming provides an
| intrinsic advantage to programming parallelism, parallelism is
| limited by hardware constraints. To best take advantage of CPU
| architectures,"function" execution needs to optimize usage of
| caching layers and execution threads. This naturally lends itself
| to the development of event loops/schedulers in functional
| runtimes like node and erlang.
| mark_l_watson wrote:
| The article is light on details, but as a polyglot programmer, I
| encourage him.
|
| I am an enthusiastic, but far from expert, Haskell programmer. I
| wonder if Brett is thinking of a more Python-like interpreted
| functional language?
| bslatkin wrote:
| Thank you! Imagine everything we like about Python, remove some
| warts, make it functional. It should feel familiar and
| appealing to a Python programmer.
| eternalban wrote:
| Based on above it seems you want to test the hypothesis that
| 'there is a python-like functional language in the space of
| FP'.
|
| Is there anything ~technical you can share beyond desires and
| disappointments that leads you to believe this is a
| reasonable hypothesis?
| bslatkin wrote:
| I've got a working interpreter and compiler for the initial
| language. I've had a few people take it for a spin and they
| were able to rapidly learn it and start contributing,
| despite having expressed frustration in trying FP languages
| in the past. All anecdotes for now!
| eternalban wrote:
| Ah, you already have it. Now we're all intrigued! Looking
| forward to the public release.
| dimitar wrote:
| So why would Clojure or Erlang or Elixir fail to satisfy the need
| for a functional language capable of taking advantage of the
| available cores?
| davidw wrote:
| Seems like he's talking about parallelism rather than
| concurrency? Erlang does the latter pretty well, but I'm not
| sure it's that great for "I have a lot of processing to do and
| I want the language to help parallelize it", especially since
| it's also not the fastest thing out there.
| lolinder wrote:
| I don't think he's arguing that the existing functional
| languages can't take advantage of all cores, it sounds like he
| believes that the existing functional languages cannot reach
| mainstream adoption because of fundamental flaws that he hopes
| to address:
|
| > My conclusion is that there are major, well-justified reasons
| for why people strongly dislike functional languages. The
| hypothesis I aim to test with a new programming language is: By
| making different tradeoffs, these issues can be mitigated and a
| more broadly-appealing functional language can be built. With
| such a language, I hope that the true promise of functional
| programming for parallel computing can be widely realized.
| bslatkin wrote:
| Exactly.
| darkmarmot wrote:
| So what advantages to comprehension or usability would you
| like to offer over Elixir? (as it doesn't really focus on
| type/category theory like most other FP languages)
| bslatkin wrote:
| I'm not an Elixir expert at all, but one important
| feature I believe is missing: explicit returns.
| Hizonner wrote:
| > once asked Guido van Rossum (the creator of Python [...]) [...]
|
| Uh-oh...
|
| You know, I was just programming in Python yesterday, and I was
| once again reminded of how ANNOYING a language it is... how
| annoying it is that it's so _popular_ that I 'm essentially
| forced to code in it.
|
| Especially now that a bunch of (probably needed) changes have
| been made in half-assed ways that interact clunkily with its
| original rather, um, idiosyncratic structure, syntax, and
| philosophy, which for a long time were determined almost entirely
| by one person's idea of what was intuitive.
|
| I mean, it's not JavaScript-level annoying or Perl-level chaotic,
| but it's a pretty damned annoying language.
|
| > Although our tools have continued to improve (such as golang),
|
| Uh-oh...
|
| Another language that grabbed some popularity by fixing some
| things, but still fails to systematically Do Things Right, even
| though we're now like 50 or 75 years into this whole computer
| thing, and are at a point where we ought to have a mature
| understanding of what Right is and the time to act with
| deliberation.
|
| One of the ways it grabbed that popularity was, of course, by
| looking familiar and unintimidating to people who don't like
| "weird languages".
|
| > By making different tradeoffs, these issues can be mitigated
| and a more broadly-appealing functional language can be built.
|
| Uh-oh...
| nextaccountic wrote:
| > He spoke of the potential for functional languages to provide a
| significant, intrinsic advantage when it comes to parallel
| computing.
|
| > (...)
|
| > If that were true, you'd expect that the many existing
| functional programming languages would have already satisfied
| this need. But in my opinion, they haven't
|
| Well there is https://futhark-lang.org/ - it runs on the GPU, and
| is awesome.
|
| On the CPU side, I think that Rust plus https://github.com/rayon-
| rs/rayon was a huge breakthrough on writing parallel programs
| using both functional and imperative programming, and future
| languages should learn from its successes. The ownership system &
| the borrow checker, plus other type-level features like the Send
| and Sync traits, were essential to enable sharing read-only data
| between threads without synchronization, or sharing read-write
| data with synchronization, all checked at compile time for data
| races (which is a huge problem to solve, and is something that
| neither Go nor Java protects against at compile time)
|
| Indeed Futhark shares a key feature with Rust: it uses uniqueness
| types to enable in-place updates, which is kind like a limited
| form of Rust ownership: if you are the sole user of some memory,
| you can update it and other code will be none the wiser. This
| kind of thing is very important to build functional programs that
| are performant in practice.
| tsegratis wrote:
| Fair point
|
| It may be better to see rust as sitting between functional and
| imperative paradigms
| klavinski wrote:
| See also the Higher-Order Virtual Machine for a functional,
| non-garbage-collected, and parallel runtime:
| https://github.com/HigherOrderCO/HVM
| nextaccountic wrote:
| Hey, that's pretty cool! The lang that targets this runtime
| is https://github.com/HigherOrderCO/Kind
| lolinder wrote:
| > Why is the gap between these two perspectives so large? My
| conclusion is that there are major, well-justified reasons for
| why people strongly dislike functional languages.
|
| Now that (nearly) every mainstream language has lambda
| expressions, there are very few patterns in functional
| programming that cannot be replicated in mainstream languages,
| which means that moving to a pure functional language now
| provides strictly fewer choices when problem solving. In order
| for a programmer to accept a language with strictly _less_
| expressive power, those new restrictions must solve problems that
| the programmer actually cares about.
|
| Rust reached adoption because mainstream systems programmers
| recognized that memory errors are a huge problem and dealing with
| the borrow checker is worth it to solve them. Static typing
| reached mainstream adoption because it made coordinating work in
| a large team dramatically easier and solved refactoring.
|
| Functional-style programming has hit the mainstream--embedded
| within imperative and OO code--but purely functional languages
| have yet to make a good case for their additional restrictions,
| and I'm not convinced that multiprocessing is that case. Golang
| mainstreamed a very effective model for multiprocessing in an
| imperative environment that solves most of the problems without
| asking programmers to completely change the way they write code,
| and that model is increasingly being adopted in other languages
| (Java's project loom, for example).
| noelwelsh wrote:
| > Now that (nearly) every mainstream language has lambda
| expressions, there are very few patterns in functional
| programming that cannot be replicated in mainstream languages
|
| I don't think this is true. Algebraic data types and exhaustive
| pattern matching, which implies a type system, are the things I
| use most in my adventures in functional programming. Mainstream
| languages (for some definition of mainstream) don't yet have
| these features.
|
| The original post doesn't mention _pure_ FP. I don 't think
| purity is that interesting when you can have a type system that
| can reason about mutation (i.e. linear or affine types, similar
| to Rust.)
| lolinder wrote:
| Kotlin and Java now have sealed classes/interfaces, which can
| provide exhaustive pattern matching and as far as I can tell
| can be used to model any ADT.
|
| EDIT: In fact, both languages are now listed as having ADTs
| on the Wikipedia page:
| https://en.m.wikipedia.org/wiki/Algebraic_data_type
|
| Also, TypeScript's union types can express ADTs, and Rust's
| enums. I don't think it will be very long before the rest of
| the mainstream languages catch up.
| noelwelsh wrote:
| Agreed, but that's why I hedged with "some definition of
| mainstream". I don't think Kotlin or Rust are mainstream
| yet, most Java places are still on Java 8 or 11, and ADTs
| in Typescript are a PITA.
| kaba0 wrote:
| I wouldn't be surprised if there would be more people on
| Java 19 than on Haskell, for what it's worth.
| wk_end wrote:
| ADT's in TypeScript aren't as nice as in a language that
| supports them natively in many respects, but "PITA" is
| really overselling it. We use them pervasively at my
| shop. In fact, the ability to synthesize them without
| naming them (because TypeScript is structurally-typed
| instead of nominally) sometimes makes them even more
| convenient than in most FP languages (OCaml excepted) -
| the ability to, say, return an ad-hoc ADT from a lambda
| without giving it some meaningless name like
| "HelperFunctionResult" can occasionally be really handy.
| nerdponx wrote:
| It's also a matter of performance. Functional non-mutating
| patterns in JavaScript and Python can be substantially,
| sometimes catastrophically, less performant than the
| procedural/imperative mutating equivalents. All functional
| programming languages that I know of which have decent
| performance rely on an optimizing compiler to some extent,
| and/or core data structures that have been optimized for
| immutability.
| smitty1e wrote:
| Python bogs down where there is excess use of the dynamic
| aspects, e.g., a large list comprehension.
|
| Go with a generator, and watch that list be more kind to
| the resources.
| nerdponx wrote:
| > Python bogs down where there is excess use of the
| dynamic aspects, e.g., a large list comprehension. Go
| with a generator, and watch that list be more kind to the
| resources.
|
| This is a micro-optimization and it's not always true.
| Generators usually use less memory, but list
| comprehensions can actually be _faster_ because the
| memory gets allocated all at once and the loop is
| performed internally inside the interpreter, instead of
| the generator possibly being consumed as a slow top-level
| loop.
|
| I was talking about examples like making a copy of a
| list/dict/object instead of replacing elements in-place,
| or using a stack of map/filter operations instead of a
| single-pass for-loop with dynamic programming.
| smitty1e wrote:
| Fair point, especially in the case of network-bound or
| disk-IO intensive work.
| adastra22 wrote:
| Algebraic data types and exhaustive pattern matching Are a
| core part of Rust.
| bryanlarsen wrote:
| ADT's and exhaustive pattern matching are in Rust. The way
| you wrote your comment makes it clear that you know that, but
| might as well make it explicit.
|
| IMO, people come to Rust because of memory safety, but they
| stay because of ADT's and similar features.
| amitport wrote:
| I would credit this model for multiprocessing to LISP family
| (Scheme/Rackt/Clojure) before golang. (Probably someone else
| would mention an earlier references :)
| lolinder wrote:
| Yep, there's a reason why I credited Golang with
| mainstreaming the concept, not inventing it. The model goes
| back quite a ways, but Golang brought it into the mainstream.
| initplus wrote:
| Any programming language represents limitations placed on the
| underlying expressiveness of the hardware. By this argument raw
| x86 asm is "more expressive" than any higher level language.
|
| The whole point of a programming language is to provide you
| with common patterns/designs to simplify reasoning about your
| program. Even base concepts like a "function" or "struct" is
| really a limitation on the underlying expressive power.
|
| Immutability/purity does solve real problems for programmers:
| it means that you only have to reason about mutability at the
| margins of your application. I think people who don't have
| experience with functional style don't realise how helpful this
| is. I choose to use functional languages because it makes me a
| better developer - I am able to write code that I am not
| diligent/smart/disciplined enough to write in an imperative
| style.
| lolinder wrote:
| I agree completely about immutability and purity--for my own
| code I strongly lean that way and try to outsource as much of
| my thinking to the compiler as possible.
|
| However, there are times where impurity and mutability are
| beneficial--whether within a single function or at the
| margins. Functional programming languages do not tend to have
| good support for these cases, because their _whole thing_ is
| representing everything in a functional style.
|
| I think this is why functional languages don't tend to get
| traction while the multi-paradigm languages do. Given a
| choice between purity and pragmatism, most engineers will
| pick pragmatism. The alternative is to intentionally remove
| tools from your toolbox, and unless those tools are
| demonstrably more dangerous than they are helpful that's a
| tough sell.
|
| My ideal language is a multi paradigm language which has
| robust, statically analyzable support for objects, imperative
| code, and functional code.
| tikhonj wrote:
| > _In order for a programmer to accept a language with strictly
| less expressive power_
|
| Sort of hard to reconcile this view with just how much more
| expressive the Haskells and Lisps of the world are compared to
| Go and Python! I've used all of these extensively and
| functional languages have consistently let me define more
| general and flexible abstractions, do a better job of
| reflecting my conceptual model of the domain in my code... all
| in substantially less code and less boilerplate (excessive
| imports aside :P) than primarily imperative languages.
|
| Functional languages don't _stop_ you from writing imperative
| code, they _allow_ you to write code that isn 't--and, either
| way, that's just one small aspect of what makes a language
| adaptable and flexible.
| lolinder wrote:
| LISP isn't a pure functional language, it's a multi-paradigm
| language that is as dynamic as they come. Its problem isn't
| lack of expressivity, it's probably that it's _too_ flexible
| (and of course the syntax throws people off).
|
| As for Haskell, I guess that gets into the question of how
| you define expressivity, which is admittedly a very fuzzy
| term. Here I meant it to mean capable of fluently expressing
| many different kinds of algorithms without having to resort
| to circumlocution.
|
| Functional programming is natively supported in almost all
| modern languages. You call a function which calls a function
| which calls a function which calls a function, return the
| result. There's no syntactic sugar, just function calls.
|
| In Haskell, while I've seen people argue that do notation may
| as well be imperative code, it _isn 't_. It's an
| approximation of imperative code using Church--Turing and a
| liberal dose of syntactic sugar, and using it effectively
| still requires you to understand the underlying monadic
| model.
| coldtea wrote:
| > _LISP isn 't a pure functional language_
|
| In the modern history-rewritten sense of the term to mean
| Haskell and purity.
|
| In the past LISP was the 100% canonical idea of what a
| functional language is, including on HN before 2010 or so.
| CrimsonCape wrote:
| This seems like an easy fix, re-release LISP with cleaner
| syntax. Lexers have come so far this seems like an easy
| fix.
|
| I can't say i've ever read the opinion that LISP's syntax
| allows more expressive programming; rather LISP itself
| allows more expressive programming at the tradeoff of the
| syntax.
| Kamq wrote:
| > re-release LISP with cleaner syntax.
|
| A lot of the flexibility of lisp relies on there being no
| difference between a list of symbols and code (for,
| example, this is how the entire macro system works).
|
| Function calls being inside the parentheses (and, really,
| all language constructs just being lists of symbols) is
| generally what people mean when they say the syntax
| throws people.
|
| These two things are at odds.
|
| You could go with Racket's method of letting people use
| alternate delimiters, but that's a fairly trivial reader
| macro in common lisp and probably not worth releasing a
| language over.
| coldtea wrote:
| > _I can 't say i've ever read the opinion that LISP's
| syntax allows more expressive programming; rather LISP
| itself allows more expressive programming at the tradeoff
| of the syntax._
|
| The conventional idea from LISPers is the other way
| around: LISP's syntax allows for more expressive
| programming, because code and data are isomorphic (so,
| macros and rewriting, etc.), and any function you make
| looks as "first class" as any native one.
|
| LISP's syntax is also said to be a better and more
| concise way than JSON (and or course XML) to describe
| arbitrary hierarchical structures.
| patrickmay wrote:
| There is no cleaner syntax than Lisp's. It is essential
| to Lisp's expressivity.
| physPop wrote:
| If you truly think "functional programming is natively
| supported in almost all modern languages" then you really
| don't know what modern FP is about.
|
| For instance implementations of monadic control flow,
| effect systems, higher kinded types, algebraic data types,
| exhaustive pattern matching etc are all laughably
| unergonomic or entireley missing in most
| "popular"/"enterprise" languages. Just having a labmda
| doesn't FP make.
|
| To me, FP in modern functional languages provides
| abstractions that enable much more straightforward problem
| solving and understandable code with fearless refactoring.
| Haskell and Ocaml are the pragmatic leaders here I think,
| with honorable mentions for things like Scala3, F#, and
| (kindof?) clojure.
|
| (edit spelling)
| karmakaze wrote:
| > strictly _less_ expressive power
|
| We have a difference in what we consider expressive. How in
| this more expressive language would you represent pure
| functions or deeply immutable datastructures if it only offered
| flexible/mutable ones? More flexible does not mean more
| expressive.
|
| If by expressive you mean conciseness, "Comparing the Same
| Project in Rust, Haskell, C++, Python, Scala and OCaml"[0] is
| of interest.
|
| [0] https://news.ycombinator.com/item?id=20192645
| lolinder wrote:
| > How in this more expressive language would you represent
| pure functions or deeply immutable datastructures if it only
| offered flexible/mutable ones
|
| With a function that doesn't cause any mutations and a set of
| classes/interfaces that offer no mutator methods.
|
| My point is that you don't _need_ to be able to have the
| compiler enforce constraints in order to express an algorithm
| --you just write the code. Having the compiler enforce
| constraints is often helpful but comes with decreased ability
| to express _other_ types of algorithms that rely on breaking
| those constraints, so the language as a whole is less
| expressive. In order for a programmer to accept those
| limitations there need to be clear advantages, and the
| advantages that functional programming proponents have put
| forward so far haven 't been persuasive to most developers.
|
| By the definition I'm working with, the most expressive
| languages are the ones that offer the fewest constraints to
| what the code can do--LISP would be a top contender.
| Expressivity isn't the highest virtue, but it is valuable and
| programmers don't give it up unless they can be persuaded it
| will be worth it.
| karmakaze wrote:
| > you don't need to be able to have the compiler enforce
| constraints
|
| Expressing such constraints and having the
| language/compiler enforce them is part of what I want from
| an expressive language. That way once I've expressed them,
| I don't have to ensure those things repeatedly for the
| entire lifecycle of the program. We each have our
| definitions and values.
| lolinder wrote:
| I should be clear that I personally agree with you
| 100%--I prefer to outsource as much as I can to the
| compiler. It's just that I also recognize that that means
| being unable to express some things that are otherwise
| possible, and that most developers don't like that trade-
| off.
| karmakaze wrote:
| I don't know what you mean. Just because C++ has "const",
| you can still make a method that doesn't mutate without
| the keyword. Seems like a "No True Scotsman" definition
| of expressiveness.
| initplus wrote:
| I feel like this doesn't make sense because mainstream
| functional languages all provide a way to express
| imperative code.
|
| In Haskell you can write an entire application using
| IO/do blocks and it will be completely imperative. In f#
| you can declare every variable mut.
|
| Functional languages don't prevent you from writing
| imperative code. They give you the opportunity to choose
| not to, and enforce it at compile time. The opposite is
| not true of imperative languages, there the type system
| cannot help you to enforce that some code is purely
| functional.
| kaba0 wrote:
| Here is a completely pure function in any imperative
| language: int add(int a, int b) {
| return a + b; }
| CrimsonCape wrote:
| Yes, this is a great example of a pillar of functional
| programming, pure functions. What is concerning is that
| your code example, like other pure function examples out
| there, implements a math operation a first grader can
| perform.
|
| It's exceedingly difficult to find a pure functional
| example that operates on tangible domain-specific data of
| objects full of state.
| initplus wrote:
| But the purity is implicit. Nothing will stop you from
| refactoring add into an impure function. As a programmer
| you have to maintain this mentally by remembering which
| types are pass by value and which are pass by reference.
| kaba0 wrote:
| Go solves no correctness problem regarding parallelism, it is
| as chock full of foot guns as any other multithreaded largely
| imperative language.
| [deleted]
| bcrosby95 wrote:
| I'm a bit confused, because I don't see the commonality between
| Go and Project Loom other than lightweight threading. Go's
| whole concurrency model is still fundamentally different from
| Java as it went all in on CSP, and Project Loom isn't.
|
| Beyond that, nothing about Project Loom fundamentally changes
| the design of all but the most performance sensitive concurrent
| programs in Java.
|
| For most of us plain programmers that Go was targeted at
| anyways, a bucket of OS threads is just fine. Now they will be
| a bucket of virtual threads, which will be nicer, but not
| exactly game changing.
| [deleted]
| karmakaze wrote:
| This other "The case for dynamic, functional programming"[0] post
| may offer hints. So I suppose it will be more like Elixir/BEAM.
|
| > Theoretically, functional programs should: have fewer bugs, be
| easier to optimize for performance, allow you to add features
| more quickly, achieve the same outcome with less effort, require
| less time to get familiarized with a new codebase, etc. With a
| dynamic, functional language you could enjoy all of this
| simplicity.
|
| In my experience use of static typing has fewer bugs and better
| performance than my usages of dynamic languages on all but small
| or short-lived projects.
|
| I suppose this will round-out Google languages: Go, Dart, and _,
| until they make their own scripting or an actual systems
| language.
|
| [0] https://www.onebigfluke.com/2022/11/the-case-for-dynamic-
| fun...
| throwway23432 wrote:
| There are a lot of people that have no interest in FP and hate
| reading functional code which involves reading and understanding
| recursion, fix-point style, partial application, currying, lazy
| evaluation, immutable data structures, lambdas, and combinators.
|
| Then you have to think of performance characteristics, and
| debugging, onboarding new engineers, and code reviews.
|
| I think it's easy to see why the industry doesn't use FP
| languages, and because of this people see no reason to even
| bother with it.
|
| I myself would rather use ML family languages or Clojure or BEAM
| but it will never happen. The majority want to use Python or Go
| since they are slim on abstraction and easy to pickup. There's no
| bullshit involved.
| twen_ty wrote:
| This must be a troll post because F# already exists and used
| extensively in production in Azure.
| moring wrote:
| > My conclusion is that there are major, well-justified reasons
| for why people strongly dislike functional languages.
|
| I hope he is also questioning the premise that functional
| programming is the reason why functional languages are unpopular.
| Every time I wanted to dive into functional programming I was
| very quickly frustrated with the abysmal tooling around them and
| while that didn't really _prevent_ me from trying, I simply found
| a better use for my time.
|
| Most recent example: Clojure wanting me to choose one of multiple
| package managers before starting my first project. Before that it
| was package management nonsense in Haskell, and before that some
| Scheme interpreter not being able to even give a stack trace on
| errors.
|
| IMHO a really underrated feature of Rust is how friendly its
| tooling is towards its users. I'd really like to see something
| like that for functional programming.
| bslatkin wrote:
| Great examples. Another question that leads to frustration is
| "can I use my existing code editor for this"? People are turned
| off when the answer is "no"
| taeric wrote:
| What examples force not using an editor? Many have a "natives
| use this" choice, but few lock you to it.
| bslatkin wrote:
| Some parentheses languages are much easier to use if you're
| familiar with a structural editor, for example.
| taeric wrote:
| All languages are easier that way, though? My kids
| learning python are best with a ton of hand holding.
| Affordances that show the structure are huge.
| bslatkin wrote:
| Agreed that seeing structure is important. I mean
| operating on it at a higher level like
| https://calva.io/paredit/
| munch117 wrote:
| The question "functional programming is great, why isn't it
| more popular?" predates package managers by decades. That
| question is older than Linux, older than Haskell.
|
| Best of luck with improving tooling, but it's not the answer.
| pyjarrett wrote:
| > IMHO a really underrated feature of Rust is how friendly its
| tooling is towards its users. I'd really like to see something
| like that for functional programming.
|
| > abysmal tooling around them
|
| F# has amazing tooling.
|
| Debugging works out of the box in Visual Studio and Rider, and
| it's impure enough I was able to get comfortable quickly and
| .NET core has a crazy amount built in (e.g. no fuss JSON
| serialization). I ported a project from C# to F# and the old
| bash/powershell scripts to publish a standalone executable are
| now just F# scripts you run with `dotnet fsi`.
| taeric wrote:
| While I do think an opinionated template would be good; I do
| also hate how some languages pretend you don't need a package
| manager.
|
| Back when code was shared more in ideas than implementations,
| this was truer. All too often today, first thing you need to do
| is import a package.
| xiaq wrote:
| As someone who's dabbled in Clojure: the project manager scene
| (lein vs boot vs deps CLI) is not nearly as bad it is may seem.
| They are different _project workflow runners_ , not completely
| different ways to write code and use dependencies. They are not
| radically different in their core job of taking your code,
| downloading dependencies and running it.
|
| If you're a beginner, you can choose any one and there's very
| little you're missing out or getting locked into. You only need
| to worry about the choice when you start having complex
| development workflows.
|
| In comparison, the JavaScript ecosystem is much, much more
| divided. There are different ways to write modules, different
| ways to build them, different package repositories, etc..
| moring wrote:
| > If you're a beginner, you can choose any one
|
| I found this to be false in practice: I did choose any one
| (lein actually, because my IDE suggested that it's the one
| you'll want to use when you don't know better). The
| consequence was that the examples from the Clojure page
| didn't work and/or printed totally different output, because
| they made a different choice.
|
| It's the kind of thing where a Clojure expert would say: they
| are different tools, of course their output is different, but
| it doesn't matter because that's only the tool output and the
| net effect is the same. But in practice, a newbie will
| struggle solving very simple problems because the tutorial
| doesn't match reality.
|
| Contrast that with the "rust book" (more or less the official
| tutorial) in which every single example behaves 100% exactly
| as described in the tutorial, from installing the toolchain
| to very complex, language-specific issues (yes, of course I'm
| referring to the borrow checker).
| slifin wrote:
| Just choose Clojure deps
|
| I kind of agree some more clarity would be helpful but we don't
| have a lot of enthusiastic young programmers in Clojure land
| who like making super accessible stuff
|
| It's just kind of assumed you'll put the work in because
| Clojure is different enough that you probably have a good
| reason to be here
|
| Btw if you want anything Clojure Google Clojure Slack and
| they'll help you there
| klysm wrote:
| The biggest thing I find myself missing from functional languages
| isn't the purity or functions - it's the clean expression of
| immutable data types combined with exhaustive pattern matching.
| All I want is algebraic data types and the ability to use the
| compiler to check my work.
| adastra22 wrote:
| Most new systems languages have this now.
| nothrowaways wrote:
| Short answer, because I am bored.
| robertlagrant wrote:
| "I want to be paid a fortune for making a programming language,
| so I need a reason."
|
| Of course, I would do the same in their position.
| bslatkin wrote:
| It's an unpaid personal open source project.
| fjfaase wrote:
| Functional is a good way to 'specify' how a certain
| calculation/change has to be performed. When working with
| distributed systems with multiple actors making changes, you have
| to treat the whole system (distribute database) as a single value
| on which your functions operate. Then you can use the commutative
| properties of function to implement transactions. (If two
| operations on the system commute, they can be applied in either
| order on the system, to result in the same state.)
|
| But from such a specifying approach to a working system, is a
| long way.
| andsoitis wrote:
| Without articulating what particular tradeoffs the author is
| balancing and sounding like they only recently
| realized/discovered the parallelism advantage possible to
| functional programming languages and paradigms, it is hard to
| know for sure, but I might venture a guess that Julia will be
| superior to what they are building: https://julialang.org
| bslatkin wrote:
| The conversation happened in ~2008.
|
| Julia has a lot of great ideas in it for sure. Why hasn't it
| gotten more popular?
| lenkite wrote:
| When it gets out of its data-science pedigree and can be used
| for standard apps. When it gets good tooling. When its stack-
| traces stop being arcane gobbledygook. When it can be
| compiled to a single binary at the command line without going
| through arcane hoops. When it gets
| interfaces/protocols/traits.
|
| At the moment, Julia is a nice language at v1alpha1 for
| scripts and data exploration.
| mrkeen wrote:
| Parallelism is concurrency (+maybe a little SIMD) done for
| _speed 's sake_.
|
| Haskell is by far the best programming experience I've ever had
| (all aspects included), and it's damn fast. It's just not
| C/C++/Rust fast _in nearly all cases_.
|
| Having said that, going functional for 'parallelism advantage'
| (speed) is a fool's errand (for now).
|
| The same thing is said about how incredibly fast JIT has
| become. (But AOT is faster!)
|
| Want speed? C/C++/Rust.
| xutopia wrote:
| What language is he working on though? Can we see the initial
| ideas in the syntax?
___________________________________________________________________
(page generated 2023-03-05 23:01 UTC)