Coconut: Simple, elegant, Pythonic functional programming
coconut-lang.org
coconut-lang.org
Also, the editor should include an auto-print option that's on by default. The first snippets I tried (copying up from below) didn't include a print statement, and thus didn't show any output when run.
Personally, I prefer FP-style (ML in particular) syntax. I think the fact that OOP languages are copying ML features like pattern matching, preference for immutability/call-by-value, and "do-notation" as a testament to FP's power.
Side note about syntax, honestly it's just glue. `<$>`, `|>`, `<*>`, and all the other symbols are just boring operations that are used so often that it's preferable to use symbols so programmers can focus on the meat. In other words:
functionA <$> functionB |> functionC <*> functionD
is easier to read than functionA(map(functionB(pipe(functionC(bind(functionD))))))But honestly there's nothing even to argue, cause the comment doesn't really say anything.
C# feels clunky in both. F# is good in FP, has good interop with OOP, but why would you?
It definitely seems easier (or is more popular) to start people on imperative programming styles, because it is easier to make analogies. From there it's a quick jump to OOP.
Did you mean to say that lambda expressions can't contain statements? But no Python expressions can! But functional programming is all done with expressions anyway, to the point where functional languages don't even have statements, so what's the problem?
>>> (lambda a, b=2:
... print(a, a, b, b, c:=3, c, *[[d,d] for d in [4]][0])
... )(1)
1 1 2 2 3 3 4 4
That's four different ways to get locals with no statements.There are simply _way_ more 'imperative' programmers/teachersTtutorials/books/... than 'functional' ones.
When teaching/instructing others, this impression only deepened.
It took a long while to even understand why functional programming has any appeal. I know that some university courses start out with scheme or lisp as a first language. But I suspect they get away with it because they have a captive audience and one that is already selected for high math tolerance.
e.g.:
a(b|c)d
vs something like: return str.StartsWith("a") && str.EndsWith("d") && str.Length == 3 && (str[1] == "b" || str[1] == "c");
Why wouldn't you consider regular expressions simple and elegant for the problem they are solving?`r"(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s`
Regex has a reputation for being "write once read never". It's primarily because it doesn't have any structure or "modularity". Functional programs also tend to pack many variables or operations in the same line without delimitation. For example Haskell's argument syntax.
I don't think this is true - it's because people don't write regex every day - I used to write a lot of web-scrapers which involved getting pretty handy with regexes, it's fine, trust me. If a regex is REALLY hard to read - it's normally because it's badly written, or because it's trying to do something genuinely complicated.
Also how are they not modular? You always build up a regex from smaller regexes, maybe the modularity isn't always easy to follow, but it is there. e.g.
{regex1}{regex2} = regex1 followed by regex2 (concatenation) ({regex1}|{regex2}) = regex2 OR regex2 (OR operator) etc.
Your URL example can be broken down into smaller modules - e.g. there's a 3-way OR block at the start that cover http(s)://, www(123)., abc.aa/ (don't understand the last one..)
This is kind of like calling js ugly because you could come up with a minified js script that is really complex and fits in one line, or if you inlined all function calls in a long C file into the main() function body. There's a sweet spot of the complexity density per LOC that humans are seemingly more-or-less tuned for, where it's often possible to get a computer to handle more complexity-dense code.
Personally, the shorter the code and the stronger the types, the faster I can tell if I made a mistake and the fewer places there are for me to make one, and that's why I like terse FP languages.
Also, what would be the procedural equivalent of the regex you linked? My guess is that if such a solution existed in procedural code, that this symbol soup you linked would be considered simple and elegant in comparison.
I'm not sure it's so complex. What's the equivalent code for recognising an URL? Regex are implemented in many languages, so this regex is, in a way, a portable library/function in most programming languages. And since it's shared, it can easily be checked way more than any single library would be.
Mainly what you're showing is that regular expresisons are awkward for matching certain types of syntax. You could have split each of the unique components in your expression into small parts and it would be much more readable.
return str == "abd" || str == "acd"
_way_ more elegant and simple, to be honest. Because the actual code would look like return match("a(b|c)d", str)I like regex as is but that would def make it more approachable for the folks I know who don't.
So yeah, I think they would call regex simple as well.
It honestly never occurred to me before watching that video that someone could mean small when they say simple. I have always understood simple to mean “easy to understand” or “low complexity”.
Admittedly Erlang also is built around the idea of exceptions everywhere.
Coconut: Simple, elegant, Pythonic functional programming - https://news.ycombinator.com/item?id=23759721 - July 2020 (63 comments)
Coconut Programming Language - https://news.ycombinator.com/item?id=23663010 - June 2020 (1 comment)
Coconut Programming Language - https://news.ycombinator.com/item?id=23339351 - May 2020 (2 comments)
Coconut: Pythonic functional programming - https://news.ycombinator.com/item?id=18815125 - Jan 2019 (169 comments)
Coconut – Pythonic functional programming language - https://news.ycombinator.com/item?id=11960692 - June 2016 (130 comments)
Show HN: Coconut – Simple, elegant, Pythonic functional programming - https://news.ycombinator.com/item?id=11936038 - June 2016 (2 comments)
My style of programming is mostly using callback with anonymous function. This restriction prevents me to using Python in serious projects.
https://coconut.readthedocs.io/en/master/DOCS.html#statement...
I appreciate that won't work well for all use cases, but it'd eliminate a lot of the pain with the current lambda implementation.
For whatever reason, the Python community declared multiline lambdas as non-pythonic and this project aims to remain pythonic, so they went with semicolons instead.
I'm not a Python developer myself, but if that was the only thing holding you back, then perhaps that reason is now slightly reduced?
Assuming that Python’s support for nested functions carries over to Coconut, it seems like a reasonably-complete feature set.
L |> map$(def (x) -> (
y = 1/x;
y*(1 - y)
))
You can also make multiline python lambdas by using brackets. That is if you can fit your code into an expression.If a function is used 2 times, 3 times, ... sure, go for it. If it's just a one-time use, please don't make a separate function.
def precise_multiples_first(max_val, divisor):
print(f"Using {max_val=}")
def sort_key(val):
if val % divisor == 0:
return 0, val
else:
return 1, val
return sorted(range(max_val), key=sort_key)
vs def precise_multiples_first(range_max, divisor):
print(f"Using {max_val=}")
return sorted(range(max_val), key=lambda val: (
if val % divisor == 0:
return 0, val
else:
return 1, val
))
(Yes I know I could've squeezed that function onto one line e.g. using ternary operator, but it was just a quick example.)interesting. So if you want to program python in a functional style, you can use Coconut to add functional features to python, or jump all the way to F# and just compile to python. Interesting to see two projects wind up in a similar place (compiling functional code to python) after starting in very different communities.
Not sure what that means for productivity and type safety.
While “any Python is valid coconut” seems appealing, in practice I don’t think this is the correct approach, since in my experience OO code is not really a good fit for the FP mental model of reasoning, and I would be happier with most of the OO features turned off.
In other news, there is now a port of Fable that compiles F# to Python.
Yes.
> What are the limitations?
It's in alpha.
> Also, is the resulting code readable?
I think so, at least in this screenshot: https://user-images.githubusercontent.com/849479/104726627-3... from this PR https://github.com/fable-compiler/Fable/issues/2339
Its author gives a talk about it here, though you may need to make a (free) account: https://skillsmatter.com/skillscasts/17237-fable-python-f-sh...
He elaborates on the above screenshot and shows F# and Python running on the same Jupyter kernel.
Python is a saner foundation to start from, though.