This whole discussion with # for typeof operator got me thinking again of the bitwise operators. I've suggested this before with tepid response, but I want to ask again...
Do we really want consume four prime ASCII symbols for bitwise operators? Other than computing a hashcode, using bitwise operators is very rare for most application code. Is it really that big a deal to use a method call instead of an operator:
line ^ col1 ^ col2 => line.xor(col1).xor(col2)
Freeing up these four symbols (and potentially << and >>) would provide a lot more flexibility for the things we do all the time. The | symbol would become unambiguous for closures, and the & symbol would become unambiguous for the field storage operator. Plus it would give us a lot more flexibility in future meta-programming features that likely would be heavily used compared to bitwise operations. Are we ready to free ourselves from this C legacy?
Thoughts?
tacticsWed 16 Dec 2009
Some old conversation on the subject at `http://fantom.org/sidewalk/topic/504`. It seems the general feelings were they weren't used a lot, but they weren't totally unused.
I had to use bitwise ops just the other day to read little endian integers from a stream. They are also used in the compiler for bitfields. But I think as soon as you step above the system/IO level, bitwise ops vanish entirely.
It would be really nice to have the syntax free for other things, especially since the majority of Fantom users will not care about bitwise ops (hell, most of them probably won't even know they exist).
Question. Do the special methods like plus and mult compile down to add and mult opcodes for native types? In other words, can we add methods not, and, or, xor, lshift, rshift to Int and still have them compile down to their respective opcodes without having to invoke the method? If so, I would vote for that. After all, bitmath is usually pretty obfuscated, and it's not like the operators make the expressions much clearer.
jodastephenWed 16 Dec 2009
My immediate response was no, we need them to help bring existing users of other languages in. But, now I'm thinking that I use them very rarely (mostly hash codes in date-time classes). So, this does make sense I think.
tacticsWed 16 Dec 2009
Another idea to bring to this. If we feel there would be an unfulfilled nostalgia for traditional C bitwise ops, we can always reintroduce them as a DSL.
// standard way of doing things
override Int hash()
{
line.xor(col1).xor(col2)
}
...
// alternatively
override Int hash()
{
Bitwise <| line ^ col1 ^ col2 |>
}
tcolarWed 16 Dec 2009
I use them once in a while, I'll be totally fine with them being a DSL.
But on the other hand, I'm not sure I like those operators to mean something else, this will most likely confuse/mislead somebody new to Fantom (That's the way Scala code often makes me feel when they go overboard with operators).
ivanWed 16 Dec 2009
+1 for DSL
brianWed 16 Dec 2009
Question. Do the special methods like plus and mult compile down to add and mult opcodes for native types?
Yes. Both 3 + 4 and 3.plus(4) are emitted to fcode as normal method calls. But the JVM will emit the call as an optimized ladd opcode.
DSL is an interesting idea. Although I'm not sure I'm ready to add a DSL like that to the core. We can always do something like that later (or someone could add it as a plugin). For the sake of this proposal let's say this is between keeping the operators as is or switching to use normal method calls.
So the full proposal is to fully remove the bitwise operators from Int and Bool:
~a => a.not
a | b => a.or(b)
a & b => a.and(b)
a ^ b => a.xor(b)
a << b => a.lshift(b)
a >> b => b.rshift(b)
This would make parsers much simplier for detecting closures since | would be unambiguous. It might also make sense to switch field storage operator from * to one of the old bitwise ops.
andyWed 16 Dec 2009
I'm on board with this change - and definitely would like to change field storage back to using &.
tacticsWed 16 Dec 2009
I'm on board with this change - and definitely would like to change field storage back to using &.
Isn't it a little ironic to get rid of old C syntax so that we can go back to using something resembling another piece of C syntax :-) But I agree.
DanielFathWed 16 Dec 2009
This would make parsers much simplier for detecting closures since | would be unambiguous. It might also make sense to switch field storage operator from * to one > of the old bitwise ops.
Wait, aren't there logical operators && and ||? Wouldn't that make | ambiguous since it is used as both logical or and closures?
tacticsWed 16 Dec 2009
No, the tokenizer takes care of that. Having a single pipe generates Token.pipe. Having two pipes in a row generates Token.doublePipe.
In closure syntax, there's never two pipes in succession. It's always |<stuff>|.
Ampersands work similarly.
DanielFathWed 16 Dec 2009
In hindsight I should have been clearer. I meant from a programmer's PoV not compilers. Though I guess it wouldn't be a problem either way.
As a completely random idea I'd make logical operators verbose (i.e. a or b , a and b ) and make bitwise operators C-like ( || and && ).
alexlamslWed 16 Dec 2009
As a completely random idea I'd make logical operators verbose (i.e. a or b , a and b ) and make bitwise operators C-like ( || and && )
Or we can just make the bitwise operators verbose.
qualidafialThu 17 Dec 2009
Or we can just make the bitwise operators verbose.
I was thinking along the same lines.
1 or 2 => 3
7 and 9 => 1
1 xor 3 => 2
alexlamslThu 17 Dec 2009
That was actually a loaded suggestion. The question is whether the following is different enough for Fantom to add sugar for it:
1.or(2.and(3)).xor(4) // Today.
1 or 2 and 3 xor 4 // Sweeeet~
KevinKelleyThu 17 Dec 2009
1 or 2 => 3
7 and 9 => 1
1 xor 3 => 2
I actually like that. I also like
true and false => false
true or not false => true
true xor false => true
Since we've got clear separation in the type system between booleans and ints, there's mostly no reason for separate operators.
heliumThu 17 Dec 2009
Right, you could use the same operators for bitwise and logical operations depending on whether you operate on integers or booleans.
Do we want a logical xor on Booleans? xor can't evaluate its second argument lazily, while and and or do.
Is this all too different from the popular C-like languages?
jodastephenThu 17 Dec 2009
I've realised that I do use the logical and and or all the time for booleans.
Its certainly quite procedural, but its also very clear, and I firmly think that the unary | and & should stay on Bool.
I don't care about | and & on Int I also don't care about Not, xor, and the shifts in general.
heliumThu 17 Dec 2009
So you explicitly want validateB and validateC to be called even if validateA already reported that A is not valid? For that you obviously need eager versions of the operators or you have to introduce one variable per validation and perform the and-operations afterwards.
In most cases such validation-tests don't cause side effects so you actually want something like:
return
validateA() &&
validateB() &&
validateC()
brianThu 17 Dec 2009
So let's explore the notion of using keyword operators. In more DSL friendly languages the way to solve this is allowing you to omit the dot/parens using an infix notation:
a.foo(b) => a foo b
No question that is elegant. However I really want Fantom to be a TOOWTDI that prevents devolution into dialects. Having that as a general purpose feature seems like it would get abused and make IDE tooling more difficult. So I really don't want to go down that path.
However I would be on board in making not, and, or, and xor keyword operators. But I don't think we can do this unless we also do it for the !, &&, and || boolean operators. That is a much bigger break from Fantom's Java/C legacy. But at the same time using keywords is much friendlier for new programmers. That would also free || up instead of |->|.
So I have no problem switching all the bitwise and logical operators to keywords. But I also worry that may be straying from the C/Java/C# syntax too much.
andyThu 17 Dec 2009
I think replacing boolean operators with keywords is outside the mission statement of Fantom - so I vote nay on that.
heliumThu 17 Dec 2009
That would still allow to use && and || as bitwise operators on Ints freeing | and &.
DanielFathThu 17 Dec 2009
My thoughts:
I like the verbosity of and, or, xor.
!, && and || have a long tradition,
!, &, | are easy(er) to write (than and, or, xor) and finally have an appropriate !=, &= and |= operators.
I don't really like not since it would be a bit tedious to write
!((x || y) && z) //old syntax
not ((x or y) and z) //new syntax
and more importantly != would have to become not ==
a != b //old way
not a==b //new way
So there is another way to do stuff. Keep !, and let &, ^| become and, xor and or respectively. When used on Bool they behave like logical operator with short-circuiting when used Ints they are bitwise operators, otherwise they serve as a syntax sugar for and( ), xor( ) and or( ).
PS. After thinking about this it here is an idea &, ^, | and ! (or &&, || as alex suggested) would act as logical/bitwise operators for Bool and Int respectively; While and( ), xor( ) , or( )not( ) would have syntax sugar in a form of infix notation.
class Foo
{
...
Foo and(Foo arg)
]
foobar := foo and Foo
Pro:
Super short
Consistent
Can still use &=
Free up || , &&
Cons:
Confusing for new commers
Semantic ambiguity
FanDocs doesn't like empty lines, grrr >:(
x || y //Bool x and Bool y, result Bool
x | y //is this Bool, Int or something else, and what could be the result?
So which one you like best (or suggest another one)?
/*Current*/
x != y
!((x || y) && b)
/*Suggestion 1*/
x and y
not ((x or y) and z)
/*Suggestion 2*/
x != y
! ((x | y) & z)
Edit: Thanks helium, I fixed it.
A bit more limited suggestion could be to give ^, |, &, ! special treatment.
ivanThu 17 Dec 2009
As I understand, the reason why there is a historical separation between bitwise and logical operators is the result of the type system lack, which is not a problem today. So I think the simplest way just to remove |, ^, & and use their logical equivalents both for ints and bools. Introducing keywords as logical operators adds noise from my point of view
heliumThu 17 Dec 2009
@DanielFath: You have two open but three closing parenthesis in all your new syntax examples.
brianThu 17 Dec 2009
OK let's bring the proposal back around to my original intention: free up the bitwise operators and require using normal method calls:
~a => a.not
a | b => a.or(b)
a & b => a.and(b)
a ^ b => a.xor(b)
a << b => a.lshift(b)
a >> b => b.rshift(b)
Existing boolean logic operators ! && || would remain the same.
Like most things this is merely taking a feature away to simplify the overall language and parsing. We are just requiring that bitwise operations use the more verbose method call syntax in order to simplify the overall language.
tcolarThu 17 Dec 2009
I like Brian's last proposal the best.
It's just simple method calls.
I don't really like adding a bunch of keywords (or, not xor etc..)
The whole discussion is that we can free those operators like & since they are so rarely used. If they are so rarely used I don't think it needs it's own syntax / keywords ... so plain methods is what I vote for.
I would still be careful on not using this operators in a context where they could be confused with their c++/java meanings ... since this could confuse a lot of people.
jodastephenThu 17 Dec 2009
I still think | and & are too important to remove from Bool. The rest I don't care about and methods are fine.
I agree with not having keyword operators in Fantom, they look and feel wrong.
brianThu 17 Dec 2009
I still think | and & are too important to remove from Bool. The rest I don't care about and methods are fine.
I've always thought that having bool support both && and & was really confusing. It is a serious left-over from C based on anything non-zero being true (just without the short circuit). I believe the only use case where they make sense is things like:
I've done that on occasion, but its pretty easily re-written in another form. This isn't about removing these operators from a single type, it is about removing them from the language. Otherwise the exercise is pointless - we actually haven't freed the symbols for other uses.
heliumThu 17 Dec 2009
Side effect causing validation code seems odd to me, but you can write it like this which isn't much more verbose:
Side effect causing validation code seems odd to me
I think that technique is used when you want to report each error you find, but keep track of if any errors were found. I actually use that pattern in myself in BuildJava. But I think this sort of code is even more rare than bitwise operators and very easily reworked. So I don't consider it a compelling reason to not simplify the language.
MoOmThu 17 Dec 2009
The most common use I have for bitwise operators is to combine several flags. For example:
win := Window(Window.FULLSCREEN | Window.BORDERLESS | Window.MODAL)
if (win.flags & Window.FULLSCREEN)
{
//The window is full-screen
}
The equivalent code with the .or() or .and() methods:
win := Window(Window.FULLSCREEN.or(Window.BORDERLESS).or(Window.MODAL))
if (win.flags.and(Window.FULLSCREEN))
{
//The window is full-screen
}
Maybe it's because I'm too used to the | and & operators, but I really think the second version looks weird and not intuitive at all. Is there a way to do this kind of things in Fantom without using bitwise operations?
brianThu 17 Dec 2009
Is there a way to do this kind of things in Fantom without using bitwise operations?
I'd like to enhance Enum to work like C# enum bitmasks eventually. That is a much more elegant solution than using C like bitmasks.
DanielFathFri 18 Dec 2009
Mostly I agree with brian; I had forgotten why we were changing the language. Still while I agree !, && and || part, I still think syntax sugar for and, or, xor and not methods should be syntax sugar in the form of infix notation.
Sure we'd gain a few keywords but at least writing and/or would be easier. Besides, the usage of such methods would be rare enough to not warrant a symbol operator and often enough so that it somewhat benefits from verbosity.
jodastephenFri 18 Dec 2009
I'm heavily opposed to and being a keyword here. There is no means to tell whether it means bitwise and or logical and? You can't tell. This is just confusing. (In fact I'd expect that reading this code would be a logical and:
if (valid and isSystemUser()) { ... }
So, I think that bitwise and and or as keywords are inappropriate.
As I've said, xor, and the shifts aren't so significant, and probably should become operators and no-one would notice. But and/or are still pretty core to expectations IMO.
DanielFathFri 18 Dec 2009
The way I see it why does Bool need and operator any way? It already has &&. Is there some use case where bitwise operator is used and where logical operator couldn't perform as well?
That way when you use syntax:
if (valid and isSystemUser()) { ... }
is just syntax sugar for
if (valid.and(isSystemUser())) { ... }
If you are using keywords (and, or) it means you are doing something which requires you to look into API. I admit it looks a bit weird but when I saw C operator for the first time, coming from Pascal I thought they looked weird too.
KevinKelleyFri 18 Dec 2009
Well, this thread's been going for a while. Here's my opinion:
Keyword operators are an interesting idea, but it's a more general thing than just swapping and for &. At least potentially, it would mean extending function-call syntax ( x = a and b; echo x ) and, while neat, doesn't really fit with one of Fantom's founding principles, which is to be instantly familiar to the Java/C world.
So while I lean toward the idea (aka the Lisp Philosophy) that rather than make a hodge-podge, we should do the minimum of things, but do them absolutely well. I lean that way, but my years in C/C++/Java/C# props me up. There's a lot of legacy there, and we shouldn't flout it without strong reason.
Removing bitwise operators (just doing that; free up the tokens and require the a.and(b) syntax) might be a reasonable place to flout tradition. It's a fairly small area of use; it clears away some old special-purpose stuff that's kind of in our way.
(The use of boolean ops for non-short-circuiting validations, should burn in hell, by the way. Is that not a most twisted way of getting what you want to happen, to happen?:-)
Anyway. Put me down as cautiously in favor of the "remove bitwise operators" proposal.
tcolarFri 18 Dec 2009
+1 to what Kevin just said.
I also think using .and() could be a bit misleading, somebody might assume it's the same as && (like it does in ruby & python and probably others) so I'll much prefer it to be something like bitAnd() or binAnd() or something (same for or), I know it's longer but the whole point of this is that thos operations are rarely used anyway.
brianFri 18 Dec 2009
This is what I suggest - I will add a warning to the compiler for the next build if you use a bitwise operator. Everyone can change their code to use normal Int methods and we can evaluate if this is something we can live with. The poor Java guys using BigDecimal have had use methods for all their math ;-)
If we can live without bitwise operators it will give us a ton of future proofing for new features, and potentially allows much more robust parsing of closures.
brianFri 18 Dec 2009
Promoted to ticket #870 and assigned to brian
jodastephenSat 19 Dec 2009
I find a.and(b) to mean a && b. I think others will too. This is very misleading.
If we have to make this change, a.bitAnd(b) is a lot clearer.
heliumSat 19 Dec 2009
+1 for renaming the currently existing and and similar methods to bitAnd and similar.
DanielFathSat 19 Dec 2009
Oh well, at least renaming it makes sense. +1 for bitAnd.
brianSat 19 Dec 2009
We already have and, or, xor methods on Int - I was not proposing to rename them, only remove their shortcut symbol. I guess the question is it worth making these method names more verbose to be explicit? I personally don't see how things will be confusing. You will continue to use ! && || for boolean logic and then these will be method calls on Ints. There is really only one meeting for not, and, or, xor, shiftl, and shiftr on Ints, so I don't really think using more verbose names really buys us anything.
Take an example from gfx:
// today
override Int hash() { w.hash ^ (h.hash << 16) }
// proposed
override Int hash() { w.hash.xor( h.hash.shiftr(16) }
// verbose
override Int hash() { w.hash.bitXor( h.hash.bitShiftr(16) }
So I definitely vote in favor of short readable names.
DanielFathSat 19 Dec 2009
Well, I think the rename idea was merely for bitAnd and bitOr (possibly bitXor or bitNot). Shift would stay the same since ambiguity only comes from comparison to logic operators.
andySat 19 Dec 2009
Leave as the short names ( and, or, etc) - I think its fine.
KevinKelleySat 19 Dec 2009
There's Bool.and, .or, .not; and there's Int.and, .or, .not. I think this pretty well follows the standard OO pattern where you overload words to give them meaning in current context.
I don't especially like the bitAnd suggestion, I think it's a case of explaining too much. and means what it always means in its context, and with method-call syntax the context is clear.
heliumSat 19 Dec 2009
and on Bool is a bit strange anyway as it doesn't get it's second argument by name.
x := false && causeSideEffect() // doesn't cause the side-effect
y := false.and(causeSideEffect()) // does cause the side-effect
Note that I deprecated Int.inverse, use not instead. I also deprecated lshift and rshift (moving the l/r to the end) to be consistent with Str.justl, justr, padl, and justr.
I was using the bitwise operators in very few places (hash codes, some color stuff). I actually think using method syntax is almost just as readable since it makes the parens more uniform. So I am definitely thinking getting rid of the bitwise operators is the right way to go for Fantom.
brianThu 14 Jan 2010
Its been about a month with the bitwise operators being deprecated.
Any comments or feedback?
I'm thinking I'll be fully removing them for the next build.
liamstaskThu 14 Jan 2010
They only pop up in a few places in my code, but I haven't had any unhealthy reactions to the current implementation. Works for me.
KevinKelleyThu 14 Jan 2010
I've converted several of my older projects to the no-operator style; in each case the long list of warnings seemed a bit daunting, but it turned out to be not so many actual changes. Even when you are doing bit-ly things, the uses only occur in a few places; most code is doing other things.
So, my opinion is to go ahead and remove em. Ill be happy to stop getting errors about inconsistent bitwise-or on my closure code. :-)
Yuri StrotTue 19 Jan 2010
+1 for removing bitwise operators at all. Int methods work fine everywhere.
A slight offtopic: I'm sure more than 50% of hash and equals methods in every application are property based. So why we need to override it every time? In java I'm always using IDE's code generation for this. But I believe the simpliest solution would be to have a special facet for example:
@unique=["w", "h"]
const class Hints
{
...
const Int? w
const Int? h
}
If we need property based hash and special equals, we can use this facet and override only equals method. I'm also sure this kind of facet can be used in another place like mapping to relational database. What do you think?
katoxTue 19 Jan 2010
@ystrot This is a tough problem - there have been some debates on this topic, for instance 209, 376 and 378.
Yuri StrotTue 19 Jan 2010
Thank you katox. There are really interesting discussions. Let me share some thoughts on all this stuff.
Use compare in equals, hash in compare, equals in compare, ...
Actually I don't like this idea. Just because these methods can be used in different areas. compare for sorting, hash for HashMap optimizing and equals for object identifying. So I don't see any advantages in restriction one area of usage by another area.
Use Comparable mixin instead of default implementation.
The only reason I see for this is have equals implementation based on compare. But it's very simple to implement and have some exceptions. In other cases it usefull to have default compare implementation to sort any list and print it, use for binary search and so on. Hash-based implementation is interesting, but as default implementation lexical order looks more user-friendly (may be it useful to have utility hash-based Comparator).
equals/compare for hierarchical classes
I believe it's so special that no make sense to talk about as a default behaviour. By default equals should check only the same type. If you need something special - just create your own implementation for your special case. However for general usage I like some mentioned ideas like limited multi-methods.
Back to my original proposal. What I want is just remove a lot of unnecessary code. By the way: currently in fantom 23 classes which have hash / equals (except native classes). All this implementation is property-based. This is also only one class compiler::TokenVal which uses different properties for hash and equals. Also only 2 of 23 classes compiler::Location and flux::Mark also have compare implementation.
I can provide statistics for my code, but I think it's the same: in most cases hash / equals are property-based and there is no explicit comparing mechnism which should be defined in a class instead of using comparators.
I've also think that facets on slots look more elegant but it doesn't provide order and doesn't allow to use slots from a base class.
andyTue 19 Jan 2010
Lets start a new topic to discuss this so we don't hijack this one ;)
brianThu 21 Jan 2010
I've removed the bitwise operators from the language grammar and compiler.
Those of you with alternate Fantom parsers will also probably want to remove these operators from your grammars.
brian Wed 16 Dec 2009
This whole discussion with
#
for typeof operator got me thinking again of the bitwise operators. I've suggested this before with tepid response, but I want to ask again...Do we really want consume four prime ASCII symbols for bitwise operators? Other than computing a hashcode, using bitwise operators is very rare for most application code. Is it really that big a deal to use a method call instead of an operator:
Freeing up these four symbols (and potentially
<<
and>>
) would provide a lot more flexibility for the things we do all the time. The|
symbol would become unambiguous for closures, and the&
symbol would become unambiguous for the field storage operator. Plus it would give us a lot more flexibility in future meta-programming features that likely would be heavily used compared to bitwise operations. Are we ready to free ourselves from this C legacy?Thoughts?
tactics Wed 16 Dec 2009
Some old conversation on the subject at `http://fantom.org/sidewalk/topic/504`. It seems the general feelings were they weren't used a lot, but they weren't totally unused.
I had to use bitwise ops just the other day to read little endian integers from a stream. They are also used in the compiler for bitfields. But I think as soon as you step above the system/IO level, bitwise ops vanish entirely.
It would be really nice to have the syntax free for other things, especially since the majority of Fantom users will not care about bitwise ops (hell, most of them probably won't even know they exist).
Question. Do the special methods like
plus
andmult
compile down to add and mult opcodes for native types? In other words, can we add methodsnot
,and
,or
,xor
,lshift
,rshift
toInt
and still have them compile down to their respective opcodes without having to invoke the method? If so, I would vote for that. After all, bitmath is usually pretty obfuscated, and it's not like the operators make the expressions much clearer.jodastephen Wed 16 Dec 2009
My immediate response was no, we need them to help bring existing users of other languages in. But, now I'm thinking that I use them very rarely (mostly hash codes in date-time classes). So, this does make sense I think.
tactics Wed 16 Dec 2009
Another idea to bring to this. If we feel there would be an unfulfilled nostalgia for traditional C bitwise ops, we can always reintroduce them as a DSL.
...
tcolar Wed 16 Dec 2009
I use them once in a while, I'll be totally fine with them being a DSL.
But on the other hand, I'm not sure I like those operators to mean something else, this will most likely confuse/mislead somebody new to Fantom (That's the way Scala code often makes me feel when they go overboard with operators).
ivan Wed 16 Dec 2009
+1 for DSL
brian Wed 16 Dec 2009
Yes. Both
3 + 4
and3.plus(4)
are emitted to fcode as normal method calls. But the JVM will emit the call as an optimizedladd
opcode.DSL is an interesting idea. Although I'm not sure I'm ready to add a DSL like that to the core. We can always do something like that later (or someone could add it as a plugin). For the sake of this proposal let's say this is between keeping the operators as is or switching to use normal method calls.
So the full proposal is to fully remove the bitwise operators from
Int
andBool
:This would make parsers much simplier for detecting closures since
|
would be unambiguous. It might also make sense to switch field storage operator from*
to one of the old bitwise ops.andy Wed 16 Dec 2009
I'm on board with this change - and definitely would like to change field storage back to using
&
.tactics Wed 16 Dec 2009
Isn't it a little ironic to get rid of old C syntax so that we can go back to using something resembling another piece of C syntax :-) But I agree.
DanielFath Wed 16 Dec 2009
Wait, aren't there logical operators
&&
and||
? Wouldn't that make|
ambiguous since it is used as both logical or and closures?tactics Wed 16 Dec 2009
No, the tokenizer takes care of that. Having a single pipe generates Token.pipe. Having two pipes in a row generates Token.doublePipe.
In closure syntax, there's never two pipes in succession. It's always
|<stuff>|
.Ampersands work similarly.
DanielFath Wed 16 Dec 2009
In hindsight I should have been clearer. I meant from a programmer's PoV not compilers. Though I guess it wouldn't be a problem either way.
As a completely random idea I'd make logical operators verbose (i.e.
a or b
,a and b
) and make bitwise operators C-like (||
and&&
).alexlamsl Wed 16 Dec 2009
Or we can just make the bitwise operators verbose.
qualidafial Thu 17 Dec 2009
I was thinking along the same lines.
alexlamsl Thu 17 Dec 2009
That was actually a loaded suggestion. The question is whether the following is different enough for Fantom to add sugar for it:
KevinKelley Thu 17 Dec 2009
I actually like that. I also like
Since we've got clear separation in the type system between booleans and ints, there's mostly no reason for separate operators.
helium Thu 17 Dec 2009
Right, you could use the same operators for bitwise and logical operations depending on whether you operate on integers or booleans.
Do we want a logical
xor
on Booleans?xor
can't evaluate its second argument lazily, whileand
andor
do.Is this all too different from the popular C-like languages?
jodastephen Thu 17 Dec 2009
I've realised that I do use the logical and and or all the time for booleans.
Its certainly quite procedural, but its also very clear, and I firmly think that the unary
|
and&
should stay onBool
.I don't care about
|
and&
onInt
I also don't care about Not, xor, and the shifts in general.helium Thu 17 Dec 2009
So you explicitly want validateB and validateC to be called even if validateA already reported that A is not valid? For that you obviously need eager versions of the operators or you have to introduce one variable per validation and perform the
and
-operations afterwards.In most cases such validation-tests don't cause side effects so you actually want something like:
brian Thu 17 Dec 2009
So let's explore the notion of using keyword operators. In more DSL friendly languages the way to solve this is allowing you to omit the dot/parens using an infix notation:
No question that is elegant. However I really want Fantom to be a TOOWTDI that prevents devolution into dialects. Having that as a general purpose feature seems like it would get abused and make IDE tooling more difficult. So I really don't want to go down that path.
However I would be on board in making
not
,and
,or
, andxor
keyword operators. But I don't think we can do this unless we also do it for the!
,&&
, and||
boolean operators. That is a much bigger break from Fantom's Java/C legacy. But at the same time using keywords is much friendlier for new programmers. That would also free||
up instead of|->|
.So I have no problem switching all the bitwise and logical operators to keywords. But I also worry that may be straying from the C/Java/C# syntax too much.
andy Thu 17 Dec 2009
I think replacing boolean operators with keywords is outside the mission statement of Fantom - so I vote nay on that.
helium Thu 17 Dec 2009
That would still allow to use && and || as bitwise operators on Ints freeing | and &.
DanielFath Thu 17 Dec 2009
My thoughts:
and
,or
,xor
.!
,&&
and||
have a long tradition,!
,&
,|
are easy(er) to write (thanand
,or
,xor
) and finally have an appropriate!=
,&=
and|=
operators.I don't really like
not
since it would be a bit tedious to writeand more importantly
!=
would have to becomenot ==
So there is another way to do stuff. Keep
!
, and let&
,^
|
becomeand
,xor
andor
respectively. When used onBool
they behave like logical operator with short-circuiting when usedInt
s they are bitwise operators, otherwise they serve as a syntax sugar forand( )
,xor( )
andor( )
.PS. After thinking about this it here is an idea
&
,^
,|
and!
(or&&
,||
as alex suggested) would act as logical/bitwise operators forBool
andInt
respectively; Whileand( )
,xor( )
,or( )
not( )
would have syntax sugar in a form of infix notation.Pro:
&=
||
,&&
Cons:
FanDocs doesn't like empty lines, grrr >:(
So which one you like best (or suggest another one)?
Edit: Thanks helium, I fixed it.
A bit more limited suggestion could be to give
^
,|
,&
,!
special treatment.ivan Thu 17 Dec 2009
As I understand, the reason why there is a historical separation between bitwise and logical operators is the result of the type system lack, which is not a problem today. So I think the simplest way just to remove
|
,^
,&
and use their logical equivalents both for ints and bools. Introducing keywords as logical operators adds noise from my point of viewhelium Thu 17 Dec 2009
@DanielFath: You have two open but three closing parenthesis in all your new syntax examples.
brian Thu 17 Dec 2009
OK let's bring the proposal back around to my original intention: free up the bitwise operators and require using normal method calls:
Existing boolean logic operators
! && ||
would remain the same.Like most things this is merely taking a feature away to simplify the overall language and parsing. We are just requiring that bitwise operations use the more verbose method call syntax in order to simplify the overall language.
tcolar Thu 17 Dec 2009
I like Brian's last proposal the best.
It's just simple method calls.
I don't really like adding a bunch of keywords (or, not xor etc..)
The whole discussion is that we can free those operators like
&
since they are so rarely used. If they are so rarely used I don't think it needs it's own syntax / keywords ... so plain methods is what I vote for.I would still be careful on not using this operators in a context where they could be
confused
with their c++/java meanings ... since this could confuse a lot of people.jodastephen Thu 17 Dec 2009
I still think
|
and&
are too important to remove fromBool
. The rest I don't care about and methods are fine.I agree with not having keyword operators in Fantom, they look and feel wrong.
brian Thu 17 Dec 2009
I've always thought that having bool support both
&&
and&
was really confusing. It is a serious left-over from C based on anything non-zero being true (just without the short circuit). I believe the only use case where they make sense is things like:I've done that on occasion, but its pretty easily re-written in another form. This isn't about removing these operators from a single type, it is about removing them from the language. Otherwise the exercise is pointless - we actually haven't freed the symbols for other uses.
helium Thu 17 Dec 2009
Side effect causing validation code seems odd to me, but you can write it like this which isn't much more verbose:
brian Thu 17 Dec 2009
I think that technique is used when you want to report each error you find, but keep track of if any errors were found. I actually use that pattern in myself in BuildJava. But I think this sort of code is even more rare than bitwise operators and very easily reworked. So I don't consider it a compelling reason to not simplify the language.
MoOm Thu 17 Dec 2009
The most common use I have for bitwise operators is to combine several flags. For example:
The equivalent code with the .or() or .and() methods:
Maybe it's because I'm too used to the | and & operators, but I really think the second version looks weird and not intuitive at all. Is there a way to do this kind of things in Fantom without using bitwise operations?
brian Thu 17 Dec 2009
I'd like to enhance Enum to work like C# enum bitmasks eventually. That is a much more elegant solution than using C like bitmasks.
DanielFath Fri 18 Dec 2009
Mostly I agree with brian; I had forgotten why we were changing the language. Still while I agree
!
,&&
and||
part, I still think syntax sugar forand
,or
,xor
andnot
methods should be syntax sugar in the form of infix notation.Sure we'd gain a few keywords but at least writing and/or would be easier. Besides, the usage of such methods would be rare enough to not warrant a symbol operator and often enough so that it somewhat benefits from verbosity.
jodastephen Fri 18 Dec 2009
I'm heavily opposed to
and
being a keyword here. There is no means to tell whether it means bitwise and or logical and? You can't tell. This is just confusing. (In fact I'd expect that reading this code would be a logical and:So, I think that bitwise
and
andor
as keywords are inappropriate.As I've said, xor, and the shifts aren't so significant, and probably should become operators and no-one would notice. But and/or are still pretty core to expectations IMO.
DanielFath Fri 18 Dec 2009
The way I see it why does
Bool
needand
operator any way? It already has&&
. Is there some use case where bitwise operator is used and where logical operator couldn't perform as well?That way when you use syntax:
is just syntax sugar for
If you are using keywords (
and
,or
) it means you are doing something which requires you to look into API. I admit it looks a bit weird but when I saw C operator for the first time, coming from Pascal I thought they looked weird too.KevinKelley Fri 18 Dec 2009
Well, this thread's been going for a while. Here's my opinion:
Keyword operators are an interesting idea, but it's a more general thing than just swapping
and
for&
. At least potentially, it would mean extending function-call syntax (x = a and b; echo x
) and, while neat, doesn't really fit with one of Fantom's founding principles, which is to be instantly familiar to the Java/C world.So while I lean toward the idea (aka the Lisp Philosophy) that rather than make a hodge-podge, we should do the minimum of things, but do them absolutely well. I lean that way, but my years in C/C++/Java/C# props me up. There's a lot of legacy there, and we shouldn't flout it without strong reason.
Removing bitwise operators (just doing that; free up the tokens and require the a.and(b) syntax) might be a reasonable place to flout tradition. It's a fairly small area of use; it clears away some old special-purpose stuff that's kind of in our way.
(The use of boolean ops for non-short-circuiting validations, should
burn in hell
, by the way. Is that not a most twisted way of getting what you want to happen, to happen?:-)Anyway. Put me down as cautiously in favor of the "remove bitwise operators" proposal.
tcolar Fri 18 Dec 2009
+1 to what Kevin just said.
I also think using
.and()
could be a bit misleading, somebody might assume it's the same as&&
(like it does in ruby & python and probably others) so I'll much prefer it to be something like bitAnd() or binAnd() or something (same for or), I know it's longer but the whole point of this is that thos operations are rarely used anyway.brian Fri 18 Dec 2009
This is what I suggest - I will add a warning to the compiler for the next build if you use a bitwise operator. Everyone can change their code to use normal Int methods and we can evaluate if this is something we can live with. The poor Java guys using BigDecimal have had use methods for all their math ;-)
If we can live without bitwise operators it will give us a ton of future proofing for new features, and potentially allows much more robust parsing of closures.
brian Fri 18 Dec 2009
Promoted to ticket #870 and assigned to brian
jodastephen Sat 19 Dec 2009
I find
a.and(b)
to meana && b
. I think others will too. This is very misleading.If we have to make this change,
a.bitAnd(b)
is a lot clearer.helium Sat 19 Dec 2009
+1 for renaming the currently existing
and
and similar methods tobitAnd
and similar.DanielFath Sat 19 Dec 2009
Oh well, at least renaming it makes sense. +1 for
bitAnd
.brian Sat 19 Dec 2009
We already have and, or, xor methods on Int - I was not proposing to rename them, only remove their shortcut symbol. I guess the question is it worth making these method names more verbose to be explicit? I personally don't see how things will be confusing. You will continue to use
! && ||
for boolean logic and then these will be method calls on Ints. There is really only one meeting for not, and, or, xor, shiftl, and shiftr on Ints, so I don't really think using more verbose names really buys us anything.Take an example from gfx:
So I definitely vote in favor of short readable names.
DanielFath Sat 19 Dec 2009
Well, I think the rename idea was merely for
bitAnd
andbitOr
(possiblybitXor
orbitNot
). Shift would stay the same since ambiguity only comes from comparison to logic operators.andy Sat 19 Dec 2009
Leave as the short names (
and
,or
, etc) - I think its fine.KevinKelley Sat 19 Dec 2009
There's
Bool.and
,.or
,.not
; and there'sInt.and
,.or
,.not
. I think this pretty well follows the standard OO pattern where you overload words to give them meaning in current context.I don't especially like the
bitAnd
suggestion, I think it's a case of explaining too much.and
means what it always means in its context, and with method-call syntax the context is clear.helium Sat 19 Dec 2009
and
on Bool is a bit strange anyway as it doesn't get it's second argument by name.But perhaps jodastephen likes it:
brian Sun 20 Dec 2009
I guess its a separate issue if we still want to keep and/or/not on Bool - I'd be in favor of just removing them, but don't have any strong opinion.
brian Mon 21 Dec 2009
I added a warning to the compiler which deprecates the bitwise operators. You just need to replace the operator with its corresponding method:
Note that I deprecated
Int.inverse
, usenot
instead. I also deprecatedlshift
andrshift
(moving thel/r
to the end) to be consistent withStr.justl
,justr
,padl
, andjustr
.I was using the bitwise operators in very few places (hash codes, some color stuff). I actually think using method syntax is almost just as readable since it makes the parens more uniform. So I am definitely thinking getting rid of the bitwise operators is the right way to go for Fantom.
brian Thu 14 Jan 2010
Its been about a month with the bitwise operators being deprecated.
Any comments or feedback?
I'm thinking I'll be fully removing them for the next build.
liamstask Thu 14 Jan 2010
They only pop up in a few places in my code, but I haven't had any unhealthy reactions to the current implementation. Works for me.
KevinKelley Thu 14 Jan 2010
I've converted several of my older projects to the no-operator style; in each case the long list of warnings seemed a bit daunting, but it turned out to be not so many actual changes. Even when you are doing bit-ly things, the uses only occur in a few places; most code is doing other things.
So, my opinion is to go ahead and remove
em. I
ll be happy to stop getting errors about inconsistent bitwise-or on my closure code. :-)Yuri Strot Tue 19 Jan 2010
+1 for removing bitwise operators at all. Int methods work fine everywhere.
A slight offtopic: I'm sure more than 50% of hash and equals methods in every application are property based. So why we need to override it every time? In java I'm always using IDE's code generation for this. But I believe the simpliest solution would be to have a special facet for example:
If we need property based hash and special equals, we can use this facet and override only equals method. I'm also sure this kind of facet can be used in another place like mapping to relational database. What do you think?
katox Tue 19 Jan 2010
@ystrot This is a tough problem - there have been some debates on this topic, for instance 209, 376 and 378.
Yuri Strot Tue 19 Jan 2010
Thank you katox. There are really interesting discussions. Let me share some thoughts on all this stuff.
Actually I don't like this idea. Just because these methods can be used in different areas.
compare
for sorting,hash
for HashMap optimizing andequals
for object identifying. So I don't see any advantages in restriction one area of usage by another area.The only reason I see for this is have
equals
implementation based oncompare
. But it's very simple to implement and have some exceptions. In other cases it usefull to have defaultcompare
implementation to sort any list and print it, use for binary search and so on. Hash-based implementation is interesting, but as default implementation lexical order looks more user-friendly (may be it useful to have utility hash-based Comparator).I believe it's so special that no make sense to talk about as a default behaviour. By default
equals
should check only the same type. If you need something special - just create your own implementation for your special case. However for general usage I like some mentioned ideas like limited multi-methods.Back to my original proposal. What I want is just remove a lot of unnecessary code. By the way: currently in fantom 23 classes which have
hash
/equals
(except native classes). All this implementation is property-based. This is also only one classcompiler::TokenVal
which uses different properties forhash
andequals
. Also only 2 of 23 classes compiler::Location and flux::Mark also havecompare
implementation.I can provide statistics for my code, but I think it's the same: in most cases
hash
/equals
are property-based and there is no explicit comparing mechnism which should be defined in a class instead of using comparators.I've also think that facets on slots look more elegant but it doesn't provide order and doesn't allow to use slots from a base class.
andy Tue 19 Jan 2010
Lets start a new topic to discuss this so we don't hijack this one ;)
brian Thu 21 Jan 2010
I've removed the bitwise operators from the language grammar and compiler.
Those of you with alternate Fantom parsers will also probably want to remove these operators from your grammars.
brian Thu 21 Jan 2010
Ticket resolved in 1.0.49