gilch / hebigo

蛇語(HEH-bee-go): An indentation-based skin for Hissp.
https://github.com/gilch/hissp
Mozilla Public License 2.0
24 stars 3 forks source link

Consider semicolons for one-liners #56

Open gilch opened 3 years ago

gilch commented 3 years ago

Python allows a semicolon for joining statements on one line, so there's precedent. It's mostly considered bad style in production code, but is useful for shell commands, although the inability to join certain statement types limits its usefulness.

for i in range(3): print(i); print(i*i)  # Python allows this.
print('hi'); for i in range(3): print(i)  # SyntaxError
for i in range(3): for j in range(3): print(i, j)  # SyntaxError
class Foo(object): def: foo(self, x): print(x)  # SyntaxError

Hebigo can do some of these already.

for: i :in range:3 print:i print: (i*i)
print:'hi' for: i :in range:3 print:i
for: i :in range:3 for j :in range:3 print: i j

But the class doesn't quite work:

class: Foo:object def: foo: self x print:x  # print in params
class: Foo:object def: foo: self x
  print:x  # print in class

But with a semicolon acting like a Lisp closing parenthesis,

class: Foo:object def: foo: self x; print:x

It's almost never used at the end of a line in Python (although this is technically allowed) and it would tend to be a long train in a Lisp, so I'd rather not allow it in Hebigo. But even internal-only, you can get doubled semicolons for reasonable use cases:

class: Foo:object
 def: foo: self x y
  print: x y
 def: bar: self a b
  print: a b

# one-liner version
class: Foo: object; def: foo: self x y; print: x y;; def: bar: self a b; print: a b

Maybe this is OK for shell commands, but it does require more careful thinking than the usual indentation-based notation. If you think of x:/; as parentheses, the Lispiness becomes more apparent. Both forms at once to show where the double came from:

class:
  Foo:
    object;
  def:
    foo:
      self x y;
    print:
      x y;;
  def:
   bar:
     self a b;
   print:
     a b;;;

You can see a train of three at the end. This wouldn't be allowed of course, but it does show the structure.

It could also make normal code more compact, but I find this less readable:

class: Foo:object
 def: foo: self x y; print: x y
 def: bar: self a b; print: a b

So, as in Python, I think they should be considered bad style in source code. I can't think of a case where it reads better, but it would make any expression possible as a one-liner, a capability that Python lacks but has some compromise support for. You can theoretically do all of your one-liners in Lissp anyway, so I'm not sure if this is worth it.

gilch commented 2 years ago

I'm wondering if this would help readability at all for a complex let destructure. I'd have to see it.

gilch commented 5 days ago

Doorstop style recommendations in Lissp gave me another idea. Use the same word to close as you opened with, like XML:

# normal formatting
class: Foo:object
 def: foo: self x y
  print: x y
 def: bar: self a b
  print: a b

# closing words
class: Foo:object def: foo: self x y /foo print: x y /print/def def: bar: self a b /bar print: a b

# Only requires last word (if unambiguous):
class: Foo:object def: foo: self x y /foo print: x y /def def: bar: self a b /bar print: a b

# Only single ; allowed:
class: Foo: object; def: foo: self x y; print: x y; /def def: bar: self a b; print: a b

# Fewer semicolons, but still unambiguous.
class: Foo:object def: foo: self x y; print: x y /def def: bar: self a b; print: a b

I do find this more readable. A single closing word would close all open hotwords up to its match. If more than one of that word is open, it will only close the closest one to its left.

I don't know that we need to reserve both characters. One or the other could serve both roles.

# ; only
class: Foo:object def: foo: self x y; print: x y ;def def: bar: self a b; print: a b
# / only
class: Foo:object def: foo: self x y / print: x y /def def: bar: self a b / print: a b

I think the slash reads a bit better. So a nameless slash will close the nearest hotword to its left, but a labeled one will close everything up to its match (and be a syntax error if there isn't one).