Forums

Require spaces around binary ops

General discussion about Cobra. Releases and general news will also be posted here.
Feel free to ask questions or just say "Hello".

Require spaces around binary ops

Postby Charles » Wed Jul 03, 2013 12:45 pm

Actually, spaces are already required around named binary ops such as "and" and "or". But we also have these binary ops:

arithmetic: + - * / ...
assignment: = += -= ...
bitwise: & | ...
coalesce: ?

I mentioned on another thread:

Sometimes I think programming languages would be better off requiring a space around binary operators such as comparisons, arithmetic, etc.


For which there were two positive responses. Although one was based on the idea of having dashed identifiers and I can't honestly say I was planning that. What I am planning if we introduced this constraint is two new convenience operators:

# Spread operator
items*.clear
# equivalent to:
for item in items, item.clear
# another example
names = customers*.name
# -->
names = for c in customers get c.name


# Safe navigation operator - avoid null ref exceptions
companyName = user?.company?.name

Both of those operators are not currently possible in Cobra because they are ambiguous with multiplication and coalesce, respectively.

Another advantage to requiring spaces around binary ops is a more uniform coding style between code bases. Also, a more consistent coding style within a given code base. Also I wouldn't have to edit patches as much. :-) I often get:
a= 1
b =2
c = 3
...in the same patch.

Playing devil's advocate, disadvantages include:

-- Impact on legacy code.
-- New users of Cobra may be turned off by what they perceive as pickiness.
-- The above new operators may still look ambiguous (although I'm skeptical of this point).

Your thoughts?
Charles
 
Posts: 2515
Location: Los Angeles, CA

Re: Require spaces around binary ops

Postby Charles » Wed Jul 03, 2013 12:48 pm

Oh, and the dot operator as in "foo.bar" would obviously be excluded. :D
Charles
 
Posts: 2515
Location: Los Angeles, CA

Re: Require spaces around binary ops

Postby nerdzero » Wed Jul 03, 2013 1:32 pm

I think spaces around all binary operators is a great idea.

I like the spread and safe navigation operator ideas as well, but I worry it would generate a lot of "write-only" code.
names = users*.company?.name

For me, that's hard to visually parse and it takes a second or two for my brain to figure out the type that 'names' gets. I suppose I could get used to reading it though once I saw it enough.

Would this be a valid use of the spread operator or would it only be for member access?
require all numbers* > 0
nerdzero
 
Posts: 286
Location: Chicago, IL

Re: Require spaces around binary ops

Postby Charles » Wed Jul 03, 2013 2:10 pm

I'd like to think that over time you'd get use to it. But we can add that to the list of potential disadvantages:

-- May make the code harder to read.

Re: your question with comparions, if we require the "all" or "any" keyword, then it's not clear if the trailing "*" is even needed. In other words, we could potentially support "all numbers > 0" right now. Well actually lets think about member access. Like:
trace any customer*.balance > 0

So actually, the trailing * makes more sense if we want to use this in more circumstances.

While we're on the subject, I'm also thinking about "accumulators" or "aggregates". Something like:
sum = 0
for item in items, sum += 0
trace sum
# how to get to one line and preferably even an expression?
# maybe:
trace 0 + items*
# general form:
trace <init> <operator> <spread collection>

That's just speculation right now. I haven't thought about all the implications. Comments are welcome.
Charles
 
Posts: 2515
Location: Los Angeles, CA

Re: Require spaces around binary ops

Postby hopscc » Thu Jul 04, 2013 1:19 am

When you posted that note I thought it might be advantageous from a standardised code presenttaion viewpoint
(like no leading mixed spaces and tabs and warning about unneeded () and various others ),

The downside is it makes cobra compiler a lot more pickier ( or more whinier) about code it accepts esp when its nitpicking about
(cosmetic) separation whitespace which is really bad when you're just trying to get something working really fast..
( provide switch for (slightly) relaxed mode on compiler ??)

The pickiness/whining is bad enough now (tho for good reasons).
I could probably go for forcing this on assign (=) as a tester...

With this, theres goanna be 2 classes of Ops then - ones that must have surrounding spaces ( and, or, not to to? , ... math +-*/, assign = +=, -+, *= /=, BitWise,
(non)Coalesce - ?,!
and ones that cant ( or shouldnt) - DOT . , QDOT ?. , STARDOT *.

(The need to correct ws around assigns (and other ops) in patches probably means that noone sees wspace here as of importance - or that we need a pretty-printer)

Re new Ops:
the safe-null operator (?.) I can see a (small)need for
(called the elvis operator ( in groovy/Ruby its a null-coalesce (?:), was proposed for Java (and maybe in others) exactly as here)
Small need cos nil tracking removes some/much of the issue .

I'm less certain about the 'spread' operator - its a new op for a (reasonably) understandable and explicit readable code - Notational shorthand is fine but it seems more obscurative than clarifying..

I dont think that construct is used enough to need its own special op ( or that making it an op would be a boost to it being used more)...
- Doesn't python have something similar (wrt comprehensions(??) which are suggested ( google python coding stds )to be only used for very simple cases - if slightly more complex clearer to expand them out fully.

I'm not sure that you assertion of being unable to support ?. and *. without space forcing is accurate.
2 new tokens '?.' and '*.' recognised only between naming ID paths and broken out to separate pieces...
I might try it for the elvis operator...

More comments on rest later...
hopscc
 
Posts: 632
Location: New Plymouth, Taranaki, New Zealand

Re: Require spaces around binary ops

Postby hopscc » Thu Jul 04, 2013 2:58 am

With the aggregator dont you also need an operators 'step' expression?

trace <init-expr> <op> <step-expression> <spreadCollection>
#for
sum = <init-expr>
for item in items, sum <op> <step-expression>
trace sum

result = 0 + 1 items*

If its just to be limited to number accumulation/summing then dont need <op> just a <step> value

Your example and above as space separated items look too much like malformed/wrong 'normal' expressions, the construct doesn't 'read' like any other expression though they look exactly like them - ( so theres a huh? moment)
the '0 +', '0 + 1' doesnt give any indication they are each separate pieces rather than some strangely placed expression ( '0 +'/'0 + 1')

How about some joining separators (like slices and counted-for) which can then elide to obvious values (also like those)
result =  0 : + : 1  items*  # spread last
result = items* 0 : + : 1 # spread first
#elided init=0, accumulatorValue =1
result = items* : + : # spread first
result = : + : items* # spread last
# Opinion: the embedded lone op just looks wrong

# If limit to simple string/numeric accumulation only then same as
#sum=<init>, for item in items, sum = sum + <step-value>
result = 0:1:items*
result = '':'-': strItems* # string of - to nItems in items

#perhaps better/more general : just two expressions - first named id in init-expr is value returned fm expression
<spread> <init-expr> : <step-expr>
result = items*: sum=0: sum+1 # spread first
result = sum=0: sum+1: items* # spread last

# More explicitly/redundantly perhaps
#<variable>=<init-expr>, for item in items, <variable> = <step-expr>
# <spread> : <result-variable> : <init-expr> : <step-expr>
result = items* : sum : 0 : sum+1
hopscc
 
Posts: 632
Location: New Plymouth, Taranaki, New Zealand

Re: Require spaces around binary ops

Postby hopscc » Thu Jul 04, 2013 3:07 am

Is there any negative collision ( syntactically or visually/conceptually) with Spread and similar syntax for a Stream (, platform-independent Type for an enumerable/iterable collection)
x as String*  = List<of String>(...) 
...
tx = x*.trim



The Spread syntax is shorthand for code walking a Stream (??)
hopscc
 
Posts: 632
Location: New Plymouth, Taranaki, New Zealand

Re: Require spaces around binary ops

Postby hopscc » Thu Jul 04, 2013 4:40 am

Assuming someone had the parsing of nil-safe working and everything working through to codegen :)
What do we all think would be the simplest way to implement a nil safe check in c# code for a platform ( like c#) that didnt have that capability/operator available or built in ?
( preferably with least code perturbation i.e without writing/rewriting the parts of the name dot id chain multiple times )
hopscc
 
Posts: 632
Location: New Plymouth, Taranaki, New Zealand

Re: Require spaces around binary ops

Postby Charles » Thu Jul 04, 2013 11:56 am

hopscc wrote:I could probably go for forcing this on assign (=) as a tester...

Sounds like an idea.

hopscc wrote:With this, theres goanna be 2 classes of Ops then - ones that must have surrounding spaces ( and, or, not to to? , ... math +-*/, assign = +=, -+, *= /=, BitWise,
(non)Coalesce - ?,!
and ones that cant ( or shouldnt) - DOT . , QDOT ?. , STARDOT *.

Right, but that's kind of the point. Both ?. and *. need to be put together to disambiguate at a syntactic level.

hopscc wrote:(The need to correct ws around assigns (and other ops) in patches probably means that noone sees wspace here as of importance - or that we need a pretty-printer)

Well at least the people submitting the patches don't. ;)

hopscc wrote:I'm less certain about the 'spread' operator - its a new op for a (reasonably) understandable and explicit readable code - Notational shorthand is fine but it seems more obscurative than clarifying..

I dont think that construct is used enough to need its own special op ( or that making it an op would be a boost to it being used more)...

Actually I find that I would use it more than the safe-null operator. This comes up all the time:
for foo in _foos, _foo.doSomething
# -->
_foos*.doSomething

Throw in "all foo*", "any foo*" and aggregation, and I think it will find plenty of use.

hopscc wrote: - Doesn't python have something similar (wrt comprehensions(??) which are suggested ( google python coding stds )to be only used for very simple cases - if slightly more complex clearer to expand them out fully.

Python's list comprehensions are most similar to Cobra's for-expression. I don't think Python has anything like the spread operator.

hopscc wrote:I'm not sure that you assertion of being unable to support ?. and *. without space forcing is accurate.
2 new tokens '?.' and '*.' recognised only between naming ID paths and broken out to separate pieces...
I might try it for the elvis operator...

foo*.bar
# currently means local var 'foo' multiplied with member access '.bar'
foo?.bar
# current means local var 'foo' nil coalesced with member access '.bar'
# although I think with those semantics, both expressions read better with spaces:
foo * .bar
foo ? .bar
Charles
 
Posts: 2515
Location: Los Angeles, CA

Re: Require spaces around binary ops

Postby Charles » Thu Jul 04, 2013 12:05 pm

hopscc wrote:With the aggregator dont you also need an operators 'step' expression?

trace <init-expr> <op> <step-expression> <spreadCollection>
#for
sum = <init-expr>
for item in items, sum <op> <step-expression>
trace sum

result = 0 + 1 items*

If its just to be limited to number accumulation/summing then dont need <op> just a <step> value

You lost me on why a step is needed when summing items.

My idea was that given a sequence of items, I want to add them all or multiply them all. If you mean to provide a step so that items can be skipped, my two thoughts are:

1) This hardly comes up in practice.
2) You can slice out the steps and then apply the operator to that

Anyway I haven't thought enough about applying math ops to streams. Can revisit later.
Charles
 
Posts: 2515
Location: Los Angeles, CA

Next

Return to Discussion

Who is online

Users browsing this forum: No registered users and 22 guests