5 2

Breaking out of the loop

Details
Message ID
<LSmkQTd--J-1@tuta.io>
DKIM signature
permerror
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

Fennel Conf 2019 and Future Fennel Changes

Details
Message ID
<20190317211622.GA15547@calvin-p51.localdomain>
In-Reply-To
<LSmkQTd--J-1@tuta.io> (view parent)
DKIM signature
pass
Download raw message
Hi Everyone!

Fennel Conf 2019 was very productive; we had lots of discussion about
using Fennel and the language itself. It was great to hear more about
the projects people have been creating with Fennel.

It was also informative to hear about the difficulties encountered in
the Fennel language and compiler. At Fennel Conf, we pinpointed some
issues that could be addressed in future releases, some small and
trivial, some complex and fundamental to the core language.

First, there is a little bit of unnecessary friction caused by Fennel
not conforming to established lisp syntax. There is also no compelling
reason to keep the current syntax besides backwards compatibility (which
should always be a consideration).

* Use of single quote (') as a string delimiter is not very useful and
  deviates from most lisp syntax highlighting (AFAIK the emacs package
  does not properly highlight single quoted strings). We could use it
  for quote inside macros.

* Allowing the tilde (~) as a symbol character robs of a character that
  could be better used for a reader macro. It is only needed for the
  special form (~=), which also already aliased to (not=).

* Commas as whitespace is a Clojure convention that also robs us of
  a reserved character that could be used for unquote, rather than an at
  symbol (@). If we disable this "feature", we could use commas for
  unquote rather than the (@) symbol, which is unexpected to lisp
  veterans.

* Explicitly declare UTF-8 support

These syntax changes are fairly straightforward, but other issues with
the core language and the compiler are more far reaching and will
require more work and discussion (some of which is already happening).

* The current parser does not preserve enough information in the
  AST to reconstruct the source code. By keeping more track of things
  like comments, we could re use the Fennel parser to create a formatter
  (preemptively named fnl-fmt) to disambiguate whitespace and
  indentation conventions and provide functionality to editors and IDEs.

* The current macro system is simply bolted on top of the compiler by
  creating new special forms for each macro. More macro facilities such
  as unquote splicing, in-source macro definitions (a bit like defmacro)
  and adding namespaces to macros are features that have been discussed.
  Writing macros should in general be made smoother with fewer gotchas.

* Post compilation, much of the data that the compiler collects is
  simply thrown out. Preserving this data (source maps, type info, etc.)
  by writing it to a file could also enable more tooling and better
  errors.

* The compiler internals have room for simplification, especially the
  API for special forms. I believe a lot of simplification can be
  achieve by making the APIs context-based and removing many parameters,
  which instead could be implicit. For example, the `emit` function
  currently takes 3 parameters, `emit(chunk, out, ast)`. This could be
  changed to just `emit(out)`, where the other data is passed implicitly
  in a context.  This kind of transformation could be widely applied
  across the compiler internals, especially in code generation.

There may be some other things I missed, but safe to say there are many
things to do. The small and trivial changes can be easily added to the
language, and will probably be the source of most incompatibility
(removing syntax tends to do that). The larger changes will of course
take more time, but hopefully should be mostly visible to people messing
with the compiler and writing special forms.

- Calvin
Details
Message ID
<87efayvabn.fsf@hagelb.org>
In-Reply-To
<LSmkQTd--J-1@tuta.io> (view parent)
DKIM signature
missing
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)
DKIM signature
permerror
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)
DKIM signature
missing
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)
DKIM signature
permerror
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