alternatives to |

alternatives to |
Photo by Patrick Federi / Unsplash

Let's explore some alternatives to | used to separate signature from type.

w scroll-by: d | w: &widget, d: (vec2 of: float) -> ø [...]
w scroll-by: d • w: &widget, d: (vec2 of: float) -> ø [...]
w scroll-by: d · w: &widget, d: (vec2 of: float) -> ø [...]
w scroll-by: d : w: &widget, d: (vec2 of: float) -> ø [...]
w scroll-by: d # w: &widget, d: (vec2 of: float) -> ø [...]
w scroll-by: d ~ w: &widget, d: (vec2 of: float) -> ø [...]
w scroll-by: d :: w: &widget, d: (vec2 of: float) -> ø [...]
w scroll-by: d -- w: &widget, d: (vec2 of: float) -> ø [...]
w scroll-by: d -> w: &widget, d: (vec2 of: float) -> ø [...]
w scroll-by: d [ w: &widget, d: (vec2 of: float) -> ø | ...]

And in a block?

[w: &widget, d: (vec2 of: float) -> ø | ...]
[w: &widget, d: (vec2 of: float) -> ø • ...]
[w: &widget, d: (vec2 of: float) -> ø · ...]
[w: &widget, d: (vec2 of: float) -> ø : ...]
[w: &widget, d: (vec2 of: float) -> ø # ...]
[w: &widget, d: (vec2 of: float) -> ø ~ ...]
[w: &widget, d: (vec2 of: float) -> ø :: ...]
[w: &widget, d: (vec2 of: float) -> ø -- ...]
[w: &widget, d: (vec2 of: float) -> ø -> ...]

I can definitively state that I prefer | as the type to code separator for a block. But when it comes to a method I'm torn. I can eliminate some choices immediately due to personal preference and shrink the set down to:

w scroll-by: d | w: &widget, d: (vec2 of: float) -> ø [...]
w scroll-by: d · w: &widget, d: (vec2 of: float) -> ø [...]
w scroll-by: d ~ w: &widget, d: (vec2 of: float) -> ø [...]
w scroll-by: d :: w: &widget, d: (vec2 of: float) -> ø [...]

~
Does the signature approximately mean a block type? Well, yes, technically that's true. We're "binding" the signature to an anonymous block of code.

::
This reminds me a lot of "constant" declarations in Jai, Go, Odin. But also in C++ where it's just syntactical noise. It looks official, special, important. It looks like a "binding".

·
So small, so innocuous. So difficult to type even on a macOS keyboard (option+shift+9). I love it, but it's not really a contender. This makes me sad.

|
What we currently have. It's the same as the divider between type | code in a block, immediate list, immediate map, class, union, enum Symmetric is nice.

Where does this leave us? I like the idea of a "binding" syntax. Is there any other use-case for it? Really variable: type is another example of binding. Colons : are overused already in the language for both keyword:selectors: and key: value maps. It might be confusing to add it in again.

If we changed the top-level syntax we could settle for something simple like w scroll-by: d [w: &widget, d: (vec2 of: float) ø | ...] and then it would be symmetrical with class declarations, which is identifier (...).

I was explicitly trying to avoid forcing everything inside the block when declaring methods. Having a visual distinction is helpful at the top-level. Was that a mistake? Simplicity and consistency are good things.

a add-with: b [
  a: int = 1, b: int = 2 -> r: int = 1000 |
  a > 0 then: [ r <- a + b ] ]

It's just... ugly like that. Which is why adding a new symbol to connect signature to type makes sense.

a add-with: b ~ a: int = 1, b: int = 2 -> r: int = 1000 [
  a > 0 then: [ r <= a + b ] ]
a add-with: b
 ~ a: int = 1,
   b: int = 2
-> r: int = 1000
[
  a > 0 then: [ r <= a + b ]
]
a add-with: b ~
a: int = 1, b: int = 2 -> r: int = 1000 [
  a > 0 then: [ r <= a + b ] ]

If replacing | is the goal here then I think ~ is the best option we've got. It's not being used for anything else right now. After all, we don't (yet?) have a binary invert of ~my-integer.

It does look a little 'magic syntaxy' to me. But so does | and ::