Good syntax for single argument methods?

I'm looking for good non-brace syntax for a single argument method call. I can't use space since it is already taken for infix operations (e.g. x + y vs. draw circle(...)). I was thinking about using hash; e.g. draw#circle(....) where circle is a method that produces a circle shape to draw. Are there any better options that have been tried before?

As for why I don't just go with braces, I'm looking for a special syntax to capture "verb on what" in a way that can more easily be read left to right without nesting.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

I always liked smalltalk for methods

no argument in smalltalk could be something like
aThing Display

any number would be something like
aThing DisplayAtX: left+7 Y: top+22

which means something like aThing.DisplayAtX:Y:(left+7,top+22)

Dot notation.

if circle produces something to draw, then this is like reverse function composition:

\x . draw (circle x) = draw ◦ circle

As I don't like unicode characters too much I would probably use a dot, as in:

draw . circle(...)

Unicode isn't a problem for

Unicode isn't a problem for me, but it would have to map to some ascii input (e.g. We can render # as open dot). But this isn't really function composition, while '.' is already used for standard noun.verb OOP syntax.

I've gone with # for now, maybe it will make sense when I post a video...soon.

Haskell dot notation

Haskell differentiates between records accessors "record.value" and function composition "f . g" depending on whether there are spaces around the dot, which works quite well.

Could try analyzing the parse tree

My compiler analyzes the parse tree to disambiguate between namespace qualified identifiers and method selection.

I.e., it has a separate pass where it simply looks whether "f.g.x" is the identifier "x" in namespace "f.g", or a method selector applied to a constant, like "x f.g".

But it's a bit weird and I don't think it's important if you don't expect many people to use the language.

(It's also pretty expensive. Direct expression is much cheaper.)

Consider an arrow-like operator

You could use something like F#'s reverse-pipe application operator:

draw <| circle(...)

or, maybe

draw << circle(...)

The idea is to cue the direction of data flow; a fancy Unicode pretty-printing could render it as an arrow of some sort.

Other points: although you could choose any precedence, the heavy weight of an arrowlike operator would seem to connote a low operator precedence -- compared to #, which looks high-precedence to me.

Also, if you do have a low-precedence application operator like this, you can use the associativity to support whichever common case you expect: right-associative for pipeline-like composition (like Haskell's $), or left-associative for curry-style iterated application.

Oh that is nice! Either

Oh that is nice! Either would work well. I could render

Ruby supports this syntax

Ruby supports this syntax while also supporting infix operators:

draw circle(1,2)

ML/Haskell has syntax which has the same number of braces, just in a different place:

draw (circle 1 2)

I'm a big fan of this syntax. The only thing it needs is a reverse application operator like F#'s |> but less ugly:

people ▶ sortBy age ▶ map name
people ▸ sortBy age ▸ map name

How do I tell the difference

How do I tell the difference between draw circle (1,2) that translates to draw.circle((1,2)) and draw(circle(1,2)). I'm already translating x + y into x.+(y), a habit I picked up from scalac. I guess we could look at the ID, if an operator, it is a member call, otherwise it is a single argument mood call, but then I can't do nice things like "0 until 10" (which means 0.until(10))

In Ruby draw circle(1,2)

In Ruby draw circle(1,2) always translates to draw(circle(1,2)) since "circle" is not an operator. draw + (1,2) translates to draw.+(1,2) because "+" is an operator. You need to know precedence for operators anyway, so you could have user declared operators with letters. Then "0 until 10" would work if you declared "until" as an operator with a given precedence.

It would be weird to have a

It would be weird to have a textual operator, and again, from scalac, operators are just strings of non-letter symbols; precedence is defined by the leading character. I could redefine until as '..' (0 .. 10 make sense?)

So do you want textual

So do you want textual operators like 0 until 10, or not? Either way you can have both single argument calls without braces and operator calls without braces as long as you can determine what is an operator and what isn't. If you restrict operators to non-letter symbols you can determine what's an operator that way. Otherwise you'll have to declare what is and what isn't an operator. You can't have both undeclared textual operators AND single argument calls without braces, because then foo bar baz is ambiguous: is that two single argument calls or a single bar(foo,baz) call. You need to distinguish those somehow.

Arities and partial evaluation.

I think you want brackets around arguments if you want fixed arities with no partial evaluation. If you allow partial evaluation strictly in argument order, then s-expressions make sense. If you want to allow arbitrary partial evaluation, then named arguments are required.

sounds like moving towards scala badness

It worries me that some folks seem to think that as long as there are rules a machine can follow, then it is ok to come up with whatever syntax they want in the name of some kind of insane chase after concise/clearer syntax.

I'd rather have things that are slightly laborious for users but remains simple, consistent, and clear.

I'm just trying to say that if yet another language gets into the rats nest of stupid syntax tricks like scala & haxe did, well, i think that sucks and is not really in the best enlightended ux self interest of the language.

obviously my $0.02 rant :-)

I don't know about Scala,

I don't know about Scala, but in my experience with Haskell and Ruby the lack of parentheses everywhere helps both readability and writability quite a bit. One thing that I dislike about Haskell syntax is that you're often typing some subexpression :

foo |

Now you type a function call in that subexpression:

foo bar|

And you realize that you need parentheses now, so you go back with your cursor and insert them:

foo bar|
foo |bar
foo (|bar
foo (bar |
foo (bar )|
foo (bar |)

Another thing is that you often get more parentheses when dealing with operators:

foo (a+b) (c-d)

Whereas in C:

foo(a+b, c-d)

Ruby syntax has neither of these issues because you can write:

foo bar(|)

and:

foo(a+b, c-d)

Or if you want even:

foo a+b, c-d

if it can be done well

then sure! But, I urge people to study deeply those other implementations with a very critical eye to find where they cause trouble. Unfortunately it seems like a lot of apologists think bad usability in these areas is OK, which personally just grosses me out. Yeah like I really want to be tracking down THAT kind of root cause for bugs / road blocks. It is often hard to turn up search results that help one quickly find out about those syntax problems. Scala has had enough time for the issues around when to use () vs. not etc. to have been bubbled up and yet most people still don't seem to see the ethical bankruptcy there, even. Still of course it is all horses for courses. My big dream would be for every language to support a simple s-expr format as well as whatever drug addled m-expr syntax they want, so that I can still use their language safely happily!

Bite the bullet and put in the brackets, e.g., factorial.[3]

Just bite the bullet and put in the brackets, e.g. factorial.[3]

That way everything is simple, consistent, and readable.

i think i concur

at least, whatever you do, if it ends up anything like all the confusion around such things in Scala, then it has failed. or e.g. in haxe 'properties' are methods that don't require "()" but in the end they are so fubar that i think i'd rather just put up with .getX() and .setX().

i think "simple, consistent, and readable" has won out for me over the years vs. being worried about having to type extra glyphs.

although it is a close race.