Comment by ~aliasing44 on ~technomancy/fennel
This macro would work, but the only problem is
(= (type last) :number)
doesn't cut it in terms of checking for ... or function calls -- it fires too easily, since the type of every macro argument tends to be "table".(macro +. [...] (let [len (select "#" ...) last (select len ...)] (if (= (type last) :number) (accumulate [sum 0 i v (ipairs [...])] (if (> i 1) `(+ ,sum ,v) v)) `(accumulate [sum# 0 _i# v# (ipairs ,[...])] (+ sum# v#)))))
Comment by ~aliasing44 on ~technomancy/fennel
[Edited because of a brain blast I had while thinking about this issue and re-reading your reply to me]
I think this can be done in a sub-optimal way without extreme difficulty.
Only the last item being fed to + needs to be checked. All earlier ones are assumed to be summable.
If this last item is ... or a function call, use a loop. Otherwise, just rely on the arg count to generate a sum a + b + c + etc. If the programmer really wants to optimize their adding, they can use local variables to explicitly denote the number of arguments to +. Otherwise, we get predictable DWIM lisp behavior that feels elegant.
Comment by ~aliasing44 on ~technomancy/fennel
I can think of a few solutions for now:
Make
+
into a macro that sees how many arguments it's being called with, and only generate a loop if it's a variadic call, else generatex + y + z ...
Make it an error to call variadic built-in operators, add new library functions
fennel.sum, fennel.mul
, etc. that are explicitly made in order to operate on multiple values, and suggest to use those in these edge cases.The thing is, this is only the tip of the iceberg for weird behaviors of fennel when using the built in math operators. I can't remember what other stuff I ran into, but I'll be sure to document it.
Ticket created by ~aliasing44 on ~technomancy/fennel
The following functions compile in really abnormal ways:
(fn a [...] (+ ...)) (fn b [...] (- ...)) (fn c [...] (* ...)) (fn d [...] (/ ...)) (fn e [...] (% ...)) (fn f [...] (// ...))The result I got from fennel 1.3.0 is:
local function a(...) return ... end local function b(...) return ( - ...) end local function c(...) return ... end local function d(...) return (1 / ...) end local function e(...) return ... end local function f(...) return (1 // ...) end return fAt the bare minimum, it would be helpful if this was some kind of error. Ideally, I would have these compile into some simple loops that are capable of handling things in more intuitive ways. For example, for the first one, something like:
function a(...) local out = 0 for i = 1,select('#', ...) do out = out + select(i, ...) end return out endThanks for making an awesome language, btw.