Skip to content

Calling Conventions #1

@sstanfield

Description

@sstanfield

Issue to discuss calling conventions around lambda/closures. This will eventually become documentation once resolved and implemented.

Defining a lambda

(fn (argname* | (optional-name default)* | &rest rest-name) expression*)

Define a lambda with zero or more normal args followed by zero or more optional args then optionally an argument to contain any remaining args after all those are used.

If using &rest the function will be provided with a proper list that is read only. Note that some read only vec operations will also work, this is a special case.

Arguments that are primitive types will be passed by value so setting them will not change calling code. Arguments that are more complex heap objects (currently Pair, Vector and String) will be passed by reference so destructive functions called on them will be reflected elsewhere.

This describes the current situation.

Closure vs lambda

A closure is a lambda that "captures" some of it's surrounding environment (i.e. variable from the scope it is declared in). This will lift locals from the stack into the heap so they will remain accessible even when the enclosing scope ends. Otherwise they behave exactly like lambdas with no special syntax.

  • Should there be something special to identify a closure? The point of this would be to stop accidentally capturing the surrounding environment but is traditionally not done- i.e. using an enclosing variable captures it and creates a closure with no special syntax required.

Point to discuss about arguments:

  • Replace &rest argname with &argname (must be in the final position- i.e. (fn (arg1 &other-args)...))
  • Should arguments be immutable by default? Maybe just heap objects so that a function has to declare that may change a parameter passed by reference? If so possible syntax could be pre-pending the argname with !, i.e. (fn (!some-vec) ...).
  • If the answer to the above is yes should this apply to let bindings as well?

Misc points of discussion:

  • Should lambdas be free to create globals (use def not at the top-level)? This seems cleaner but may restrict some lispy stuff.
  • Consts? Should they just be read-only globals? Can they be redefined? If not is ok to try as long the value does not change (making it easier to re-load code)? Not be redefinable would make them more "const" but would make image based dev harder.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions