evincarofautumn / kitten

A statically typed concatenative systems programming language.
http://kittenlang.org/
Other
1.1k stars 42 forks source link

Avoid syntax that requires local variables #166

Open trans opened 7 years ago

trans commented 7 years ago

Are there (or can there be) combinator forms of conditionals? They way things are, it looks like one must use local variables if there are any conditionals.

evincarofautumn commented 7 years ago

Sort of. If you omit the condition from an if, it’s taken from the stack, and the branches can have any stack effect as long as they match.

define cond<R..., S...> (R..., (R... -> S...), (R... -> S...), Bool -> S...) {
  -> t, f, x;
  if (x) { t } else { f } call
}

=>

define cond (…) {
  -> t, f;
  if { t } else { f } call
}

=>

define cond (…) {
  if { drop } else { swap drop } call
}

And a missing or empty else is the same as the identity function:

=>

define cond (…) {
  if (not) { swap }
  drop call
}

I just don’t tend to use this style in examples much. There are some things that require locals, like capturing a value in a closure or vector, but you can wrap these in combinators. I’ve been thinking about how to fix those cases, too.

trans commented 7 years ago

Great. That works.

evincarofautumn commented 7 years ago

Currently, list literals cannot draw elements from the stack. I propose using the _ placeholder to denote this. Just as for local variables, elements would be popped in the same order they were pushed:

[1, 2, 3]
// ==
1 [_, 2, 3]
1 2 [_, _, 3]
1 2 3 [_, _, _]
2 [1, _, 3]

define singleton<T> (T -> List<T>):
  -> x;
  [x]
// ==
define singleton<T> (T -> List<T>):
  [_]

This could also be done for quotations:

define quote<T> (T -> (-> T)):
  -> x;
  { x }
// ==
define quote<T> (T -> (-> T)):
  { _ }

And for string literals, with an escape \_:

instance show<A, B> (Pair<A, B> -> List<Char>):
  unpair -> x, y;
  [x show, " ", y show, " pair"] concat
// ==
instance show<A, B> (Pair<A, B> -> List<Char>):
  unpair "\_ \_ pair"

This might be a point of confusion for some people, however, because the syntax for operator sections is still (x @) / (@ x), not (x @ _) / (_ @ x). Changing to the latter would allow for prefix and postfix operators in addition to infix operators, but I feel that would introduce too much complexity for little benefit.