HuoLanguage/huo

Contribution Request: functional programming functions

Opened this issue · 9 comments

Would it be valuable to add functions such as each, filter, fold etc. to the core language? Or even just part of the standard library? I'm more than happy to contribute such features.

Hi @chickencoder ! I'm trying to keep the core language small, but I definitely think there are a couple functions that could be added. Currently, we have each and reduce, but map and filter might be useful as core language features.

I think if you want to add map or filter you can just open pull requests for those changes. If you want to add anything else open an issue and we can have a discussion about whether it is appropriate for the core language or the standard library.

Okay great I'll attempt to implement map and filter :)

BTW @chickencoder maybe you figured this our already but core functions that manipulate the AST in non-trivial ways should be executed by the function called apply_execution_function. Anything simpler is put in core_functions.

Question about map: should it modify the array in-place, or should it return a copy?

@TheLoneWolfling that relates to your question in #55. I think we should opt for immutable arrays. So:

(let x [])
(let y x) ; y is now a copy of x
(push 1 y) ; y = [1] and x = []
(let z [1, 2, 3])
(let a (map z item index (* item item)))
; z = [1, 2, 3] and y = [1, 4, 9]

But that makes me wonder, should we allow the simple assignment of arrays at all? Perhaps that should throw an error, especially since copying nested arrays would be costly. Maybe we can have a copy function to make it explicit:

(let x [1, 2, 3])
(let y (copy x))

Does that sound good to you @TheLoneWolfling ?

That could work. Call and reference by value, in other words.

(Though note that what you are suggesting is not immutable arrays. If it was, (push 1 y) would return a new array with 1 pushed to it, and y wouldn't have changed.)

If you have something like this:

(f (index (index (index x 1) 2) 1))
(g (index (index (index x 1) 2) 2))
(h (index (index (index x 1) 2) 3))

You cannot pull the common index subexpression out into a let definition, which could be annoying.

I'd prefer not to require a copy function, though. It'd end up being used so often that it'd just end up being syntactic noise.


I don't see how this deals with #55, however.

Consider what happens when you pass an array to this:

(def f x (g x x))

where g is another function. You'll end up with multiple references to the same array, which is the exact problem we're trying to avoid. Unless you're talking about making an array copy at every function call for every array parameter, which would be absurd (and wouldn't allow you to do many things in functions, to boot).

Hmm, yes I suppose #55 is about references to arrays and this issue is about updating arrays. And I agree about copy being syntactic noise, one of the things I specifically tried to avoid with the syntax of Huo was syntactic noise so I'm happy you pointed that out. Would it be confusing if map returns a new array and push modifies the array passed into it?

After thinking about it a minute: have all of said functions modify the array in-place, if you take the value route. If you want a new array, it's easy enough to copy said array before calling the function.

Or have separate _copy functions.