Live data from Hacker News

Ante: A low-level functional language

antelang.org

101–110 of 226 posts

Re: Ante: A low-level functional language

#101
post #49

Earlier quoted context omitted.

I have heard that if you count { and ( as parens, a Java program for example has just as many parens as. lisp one. A lisp paren can do both jobs: expression and scopes.

> A lisp paren can do both jobs: expression and scopes. Using different symbols for different purposes makes sense, it helps humans to parse correctly faster.

That's right, which is why the parenthesis is combined with a leading symbol like (let ...).

Mainly, you don't look at the parenthesis when reading; you look at that let and your eyes rely on indentation for structure.

Re: Ante: A low-level functional language

#102
post #98

I'm confused how data structures work in this language, and there's no documentation about it as far as I can tell. Is this going to be a Rust-style vectors+iterators system? It it going to use purely-functional concatenative structures? The first example you show invokes `map` and `sum` over an Array, but what is this code actually doing? Making a copy of the data in the array? Creating a mapping iterator?

Rust-style with Vecs+Iterators is the current style, yes. So the map+sum example creates an iterator rather than copying the array.

I'd like to remove iterators in favor of Generators (implemented with Algebraic effects) in the future though since they're much easier to define. Actually switching over is on hold until effects are implemented and speed tests are done to ensure they're compareable speed to iterators (which they should hopefully be due to monomorphisation of effects + handlers).

Re: Ante: A low-level functional language

#103
post #51

Earlier quoted context omitted.

> 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.

What creates that distinction ? in the lisp / fp world you quickly stop considering functions as separate entities.

The function represents the operation or computation you want to perform. The arguments represent inputs or parameters for that operation or computation.

Of course, theoretically you could also view the function as a parameter of the computation and/or the arguments as specifying an operation (in particular if those are also functions), but for most concrete function invocation that's not generally the mental model. E.g. in "sin(x)" one usually has in mind to compute the sine, and x is the input for that computation. One doesn't think "I want to do x, and `sin` is the input of that operation I want to do". One also doesn't think "I want to do computation, and `sin` and `x` are inputs for that computation". It's why you may have mentally a sine graph ranging over different x values, but you don't imagine an x graph ranging over different functions you could apply to x.

Re: Ante: A low-level functional language

#104
post #96
post #64

Earlier quoted context omitted.

I thought more languages did this but at least nix and ocaml do not actually behave like I thought. In Ruby however it is a bit more ugly def f x x + 1 end puts f f 1 > 3

I don't understand your objection, what output would you like to see instead?

GP's point is that while yes, we know since `f` has arity 1 there's no ambiguity, in general you might not have the arity of any given function fresh in your head, and therefore can't tell (in Ruby) just from looking at `f f 1` whether it means a single invocation of an arity 2 function, or two invocations of an arity 1 function

Re: Ante: A low-level functional language

#105
post #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…

Thanks for the explanation, I will definitely check out the docs on algebraic effects!

Re: Ante: A low-level functional language

#107
post #90

Earlier quoted context omitted.

Thanks for sharing! The dot product example gave me pause because map2 seems to be the same as zipWith. Does that exist in Ante? Without context I might have thought map2 was going to act as bimap. Take that for what you think it's worth :) Also I might be having a brain fart -- but isn't the dot product in your example equal to 32?

map2 is indeed another name for zipWith. I believe I got that name from Racket if memory serves. Compared to zipWith I like its symmetry with the 1 argument map. I also wasn't aware of bimap! I can't seem to find a function of that name online, though I did find the BiMap haskell package, is that what you're referring to? And yes, the dot product should be 32, thank you :)

Not OP but they meant https://hackage.haskell.org/package/base-4.16.1.0/docs/Data-...

As you have the normal map function for Functors (using Haskell):

  > :t fmap
  fmap :: Functor f => (a -> b) -> f a -> f b
you can have bimap for Bifunctors:

  > :t bimap
  bimap :: Bifunctor p => (a -> b) -> (c -> d) -> p a c -> p b d
which specialised to pairs is:

  > :t bimap @(,)
  bimap @(,) :: (a -> b) -> (c -> d) -> (a, c) -> (b, d)

Re: Ante: A low-level functional language

#108

Functional is always at odds with low level programming because of heap allocation. You can't control it because of immutability. Just a simple map operation does a heap allocation. How does Ante avoid this problem and give the user control of the heap? The mechanism should be made clear in the introduction as browsing the documentation doesn't make it clear to me.

The plan is to give users control through the Allocate effect which can be handled in any way desired as long as it returns some memory. It is similar, but easier to use since it is an effect, to zig's approach of "pass the allocator everywhere." I say easier to use since effects are automatically passed around where necessary and propagated via function signatures and can be inferred.

The specific design is still in question though. For one, an effect like Allocate will be almost ubiquitous throughout each function so care is needed to not clog up signatures too much. There's a few potential solutions here if you're interested. From including Allocate within the row-type of a larger effect like `IO = can Allocate, Read, Write, ...` to encouraging effect inference on functions versus manual annotation.

Re: Ante: A low-level functional language

#109
post #62

How does string interpolation work? In what context, exactly, are the placeholders checked and/or evaluated? How are missing or incompatible placeholder values handled? The semantics aren't obvious (for instance, how do you deal with string inputs, which would contain placeholders that cannot be checked in advance?).

String interpolation works by expanding to the concatenation of several strings. So a string like "the ${foo}." is expanded to "the " ++ foo ++ ".". There are some things I'd like to change about the current design. Namely it should probably defer to a StringBuilder of sorts, and it should possibly do it lazily so that interpolation can be used in log calls without worry of whether logging is enabled. These are all c…

So it's purely syntactic sugar around concatenating plain string literals and various expressions, it has no relation to print or other I/O, and in case a string comes from input (BTW, I don't see any mention of serious IO besides print for "logging") or from some computation it isn't subject to interpolation.

I don't think limiting string interpolation to enhanced string literals in code (leaving out generic strings) in order to allow static checking is a practically acceptable restriction. For example, logging frameworks meant for long-running application tend to specify message templates in configuration files or databases, possibly hot-reloading them at runtime.

Re: Ante: A low-level functional language

#110
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.

To be clear, I didn't say they were equivalent. They're equivalent up to isomorphism, not equal.
Post reply on HN