~technomancy/fennel

Discussion of the Fennel programming language for contributors and users

https://fennel-lang.org

4 2

Breaking out of the loop

Details
Message ID
<LSmkQTd--J-1@tuta.io>
Download raw message
Hi everyone,

I was reading documentation and stumbled upon a lack of early returns in Fennel: https://github.com/bakpakin/Fennel/blob/master/tutorial.md#gotchas. <https://github.com/bakpakin/Fennel/blob/master/tutorial.md#gotchas> Say, how does one look for an element in an array? I can think of doing this recursively and manually calling next() on table, but not sure if this is the preferred way.

Also, it looks like there had been a break special form before, but it was removed. What's the rationale of not having returns and breaks and what are the alternatives?

Thanks,
Slava
Details
Message ID
<87efayvabn.fsf@hagelb.org>
In-Reply-To
<LSmkQTd--J-1@tuta.io> (view parent)
Download raw message
hayohayo@tuta.io writes:

> I was reading documentation and stumbled upon a lack of early returns
> in Fennel:
> https://github.com/bakpakin/Fennel/blob/master/tutorial.md#gotchas. <https://github.com/bakpakin/Fennel/blob/master/tutorial.md#gotchas>
> Say, how does one look for an element in an array? I can think of
> doing this recursively and manually calling next() on table, but not
> sure if this is the preferred way.

Good question. For most codebases you will want to pull in a 3rd-party
library like Lume or Luafun since the Lua standard library is so small.

  https://github.com/rxi/lume

But if you just want this one function, I'd use this:

(fn find-index [t v i]
  (let [this (. t (or i 1))]
    (if (= this v) (or i 1)
      (= nil this) nil
      (find-index t v (+ 1 (or i 1))))))

> Also, it looks like there had been a break special form before, but it
> was removed. What's the rationale of not having returns and breaks and
> what are the alternatives?

One nice thing about lisps is that their syntax is consistent. One of
the consistent factors is that the value in the tail position of the
function definition is always the return value. Early returns and breaks
violate these assumptions and force you to look more closely at the code
to see what's really going on.

-Phil
Details
Message ID
<LSqBynG--3-1@tuta.io>
In-Reply-To
<87efayvabn.fsf@hagelb.org> (view parent)
Download raw message
Dec 3, 2018, 8:34 AM by phil@hagelb.org <mailto:phil@hagelb.org>:

> But if you just want this one function, I'd use this:
>
> (fn find-index [t v i]
>   (let [this (. t (or i 1))]
>     (if (= this v) (or i 1)
>       (= nil this) nil
>       (find-index t v (+ 1 (or i 1))))))

Yes, I see. This one is indeed very specific. Yet, I assume, even then
it may be less efficient than Lua's for with break/return?

> One nice thing about lisps is that their syntax is consistent. One of
> the consistent factors is that the value in the tail position of the
> function definition is always the return value. Early returns and breaks
> violate these assumptions and force you to look more closely at the code
> to see what's really going on.

Interesting, thanks. Don't all current looping constructs are statements
though?.. (each), (for), (while).

Thanks,
Slava
Details
Message ID
<87a7llvrvg.fsf@hagelb.org>
In-Reply-To
<LSqBynG--3-1@tuta.io> (view parent)
Download raw message
Slava Lopata <hayohayo@tuta.io> writes:

> Yes, I see. This one is indeed very specific. Yet, I assume, even then
> it may be less efficient than Lua's for with break/return?

I can't think of a reason it should be; Lua has proper tail calls, so
the recursion here basically compiles to a simple goto.

> Interesting, thanks. Don't all current looping constructs are statements
> though?.. (each), (for), (while).

No, lisps don't have statements; these are simply expressions which
return nil.

-Phil
Details
Message ID
<LSudmJ1--3-1@tuta.io>
In-Reply-To
<87a7llvrvg.fsf@hagelb.org> (view parent)
Download raw message
3, 2018, 8:27 PM by phil@hagelb.org <mailto:phil@hagelb.org>:

>> Interesting, thanks. Don't all current looping constructs are statements
though?.. (each), (for), (while).
> No, lisps don't have statements; these are simply expressions which
return nil.

What I am trying to say, currently (each), (for) and (while) loops
in Fennel - all are basically "statements", they are used for
side-effects. In this case value in the tail position becomes
less relevant, I guess.

Slava