Live data from Hacker News

Ante: A low-level functional language

antelang.org

51–60 of 226 posts

Re: Ante: A low-level functional language

#51
post #5

Earlier quoted context omitted.

> Is there a reason why you would make fn(1) and fn 1 equivalent? If your standard function call convention is just `f x`, but you also support precedence operators, then `f (x)` automatically becomes possible. It reminds me of an old Lisp joke, though: f x -- too mathematical! (f x) -- too many parenthesis! f(x) -- just right!

As an old lisp fan, I never got this. (f x) and f(x) have the same number of parenthesis. and the nice thing about (f x) is that the parenthesis group f with x; so you have the whole call inside the (). Consistent and simple to understand. vs i.e. print(f"a string"), where it isn't even clear that the "f" is a function call.

> the nice thing about (f x) is that the parenthesis group f with x

The drawback is that they are put on the same level, whereas in most people’s minds the function is a fundamentally different thing from the argument(s). The “f(x)” syntax reflects that asymmetry.

Re: Ante: A low-level functional language

#52
post #40
post #3

The syntax looks a little funky to me but it's still quite interesting. Is there a reason why you would make fn(1) and fn 1 equivalent? For me personally it makes readability worse and looks strange when chaining functions like in their last example on their landing page. On mobile horizontal scrolling through the code snippets will trigger switching to the next snippet on my phone.

> Is there a reason why you would make fn(1) and fn 1 equivalent? 1 and (1) are isomorphic. A single term tuple can be converted to the single term, and vice versa. Having an implicit conversion doesn't seem too crazy. The biggest issue I suspect would be confusion about the most idiomatic way, or a mix of styles in real-world code bases, that causes confusion or inconsistencies (increases cognitive load for the read…

I don't think this applies in this case. The brackets here are used for resolving precedence only. They are a syntactic feature which are not represented in the language semantics.

Where brackets are used in some languages to construct tuples, you generally need special syntax to represent the case for 1-tuples, like Python where "(1)" is equivalent to "1" but "(1,)" is a 1-tuple containing a single 1 value.

Also in most FP semantics, x and the 1-tuple containing x are not equivalent so the mathematical isomorphism doesn't hold. The tuple itself could be undefined (bottom/unterminating or null, if the language has such a concept), or could contain an undefined value or could be completely well-defined. These three cases are not represented in the semantics of the unbundled value.

Re: Ante: A low-level functional language

#53
post #41
post #40

Earlier quoted context omitted.

> Is there a reason why you would make fn(1) and fn 1 equivalent? 1 and (1) are isomorphic. A single term tuple can be converted to the single term, and vice versa. Having an implicit conversion doesn't seem too crazy. The biggest issue I suspect would be confusion about the most idiomatic way, or a mix of styles in real-world code bases, that causes confusion or inconsistencies (increases cognitive load for the read…

I'm not sure I like a single item tuple being equivalent to just the item. Can you ask for the length of a tuple? The length of a tuple with two 100 element lists would be 2, and if you looked at the tail the length would be 100.

Right. In particular if you identify tuples with lists (which seems reasonable), you run into typing problems, because singleton lists/tuples suddenly have to be unified with the element type.

Re: Ante: A low-level functional language

#54

How is this low level exactly?

quoting the github readme: > In general, ante is low-level (no GC, values aren't boxed by default) while also trying to be as readable as possible by encouraging high-level approaches that can be optimized with low-level details later on.

with no GC, is there compile time segfault checking like rust?

Re: Ante: A low-level functional language

#55
post #48

Earlier quoted context omitted.

> f x -- too mathematical! :) yet we are very happy to use the same syntax in shell scripts or the shell itself.

I guess the difference is that nesting calls (commands) is much less common in the shell, and (closely related) commands don’t really have a return value.

On the shell, it is all the other way around, so to use command substitution it is like this:

    f $(g x)
To pass the output of g x to f.

Re: Ante: A low-level functional language

#56
post #5

Earlier quoted context omitted.

> Is there a reason why you would make fn(1) and fn 1 equivalent? If your standard function call convention is just `f x`, but you also support precedence operators, then `f (x)` automatically becomes possible. It reminds me of an old Lisp joke, though: f x -- too mathematical! (f x) -- too many parenthesis! f(x) -- just right!

> f x -- too mathematical! :) yet we are very happy to use the same syntax in shell scripts or the shell itself.

I've heard this argument before, but this isn't true.

In shell, f x y z, x y z are all augments to f. Doesn't matter if f takes one argument, all are passed to the function.

With many functional languages this gets very confusing. IE what ie what does `f f x` do? In shell I know for sure.

In the example f f x, it might be easy to parse. But in f x y z, any of x y z might be functions.

Re: Ante: A low-level functional language

#57

How is this low level exactly?

low is relative :-D my thought exactly.

IMO the only low level language is assembly. Everything else is some form of abstraction. C/C++ and the likes I tend to call lower, since in 2022 it is closer to the hardware, and then sugar languages like python, c#, js, and the likes I call high level.

Re: Ante: A low-level functional language

#58
Hello, author here! As the website says, the compiler itself is still in a very early state where basic things like functions, types, traits, inference, monomorphisation, and codegen are implemented. The fun stuff of algebraic effects, lifetime inference, and refinement types are not however. Though I can elaborate on implementation strategies of these for anyone curious. For example, algebraic effects in existing languages can be quite slow at runtime due to the use of continuations, the translation to a monad stack, and/or dynamically finding handlers at runtime. It is my plan to monomorphise them away and inline all these cases as in the following paper (1). With this, handlers are inlined into functions, continuations are normal closures, and continuations that aren't called multiple times are inlined.

(1) Zero-cost Effect Handlers by Staging: http://ps.informatik.uni-tuebingen.de/publications/schuster1...

Re: Ante: A low-level functional language

#60
post #11

Looks very cool! Can somebody enlighten me what's happening in the Algebraic Effects example? Specifically this part: handle f () | flip () -> (resume true + resume false) / 2.0 Does `handle f ()` call `calculation` and the `| ...` part "injects" the `flip` effect? I am also quite confused by the part following `| flip ()`. It somehow returns true or false with a probability of 50%? And why does this give you the exp…

Author here, a good way to understand algebraic effects is as "resumeable exceptions." In this case the expected_value handler says to run `f ()` and whenever that computation "throws" a `flip ()` effect to handle it by resuming the computation with the value true returned for flip. The continuation continues as normal, subsequent uses of flip are also handled until the computation finishs. Then we evaluate the rest of `+ resume false) / 2.0` and resume the computation (a second time!) in the same place, this time with the value false. Finally, we add both values returned and divide by two to get the expected value.

This way of computing expected value works because for each flip we essentially have a case-split: the value can be true or false with a 50-50 chance, so the expected value of the whole thing is is 0.5 * the result of the true branch + 0.5 * the result of the false branch!

This is more of a fun use of effects than a practical one. If you're still curious about effects, check out the full page on them here: https://antelang.org/docs/language/#algebraic-effects which includes some actually useful effects like State, Generators, looping constructs, parsers, etc.

Post reply on HN