HuoLanguage / huo

interpreted language written in C
MIT License
212 stars 21 forks source link

Contribution Request: functional programming functions #52

Open chickencoder opened 8 years ago

chickencoder commented 8 years ago

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.

incrediblesound commented 8 years ago

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.

chickencoder commented 8 years ago

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

incrediblesound commented 8 years ago

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.

TheLoneWolfling commented 8 years ago

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

incrediblesound commented 8 years ago

@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 ?

TheLoneWolfling commented 8 years ago

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

incrediblesound commented 8 years ago

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?

TheLoneWolfling commented 8 years ago

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.

TheLoneWolfling commented 8 years ago

Or have separate _copy functions.