Open alexnask opened 10 years ago
Would g1 = parent ? child ? child ? child
work, or would it break the ternary operator?
Well, what would be the semantics of:
a := b ? c ? d : e
Also, that would mean that we must force a space before the ? operator (becuase ? is valid in ooc identifiers), which I can't help but think is bad practice.
@shamanas That's already the case with the ternary operator. I had fun making that work in NagaQueen...
On Fri, Aug 22, 2014 at 1:44 PM, Alexandros Naskos <notifications@github.com
wrote:
Also, that would mean that we must force a space before the ? operator (becuase ? is valid in ooc identifiers), which I can't help but think is bad practice.
— Reply to this email directly or view it on GitHub https://github.com/fasterthanlime/rock/issues/810#issuecomment-53050942.
@fasterthanlime @davidhesselbom
I still think this operator would be a great idea, how about using <space>?
?
For example:
// All fine!
g1 := parent ?child ?child ?child ?? getDefault()
g1 := parent ? child ? child ? child // This doesn't parse
Well... parent ?child
makes it look like I'm asking whether child
, not parent
, is null. And letting the parser be so sensitive to where I put the space is kind of scary. Almost like bash :fearful:
Both good points.
Perhaps actually using ?.
is the solution (allowing spaces in between), although the dot does make the user think the operator is similar to the dot operator, when it obviously isn't.
I'm at a loss again I guess :/
Me too. I don't think ?.
is a good idea either, because that's not what the dot usually does in ooc. In C# it makes a lot of sense, though! I think the problem to begin with is the fact that ?
is allowed to terminate identifiers (which isn't a problem in itself, just unconventional, and leads to problems years later (i.e. now)).
Yeah, I can't think of any "good" syntax.
I guess I'll just leave it to rest for now.
What about using <$>
, sort of like Haskell? Or just $
?
"We ran out of ?
so we decided to run with $
instead"
I'd like something that involves ?
, as it is already used by the nullco operator and I think it somewhat naturally brings up null checking.
It appears it can't be used though, so $
could do, it is somewhat noisy though, I wouldn't want ooc to suddenly turn into perl :P
Ok then...what about \
? Like K?
Or ∃
.
(I'm joking)
I personally think ?>
would be an OK choice (although foo?>bar
can be confusing, assuming foo?
and bar
are variables) and I prefer $
over \
(\
is already used to continue a statement on another line, like C, btw).
In the end, I think we all agree that it is a really nice feature but it's up to Amos to take this decision.
I think we can live without it for now, until a decision is made, it is relatively simple to implement once we do so (trivially translated into a series of ternary expressions)
Yeah, it's just frustrating to know that all that's keeping it from becoming something we can use is that we can't figure out how to write the operator. It's like would-be parents deciding not to have a baby until they've figured out a good name for it.
@davidhesselbom
I can hack up ?>
on one of my branches if you wish, then merge it with its final syntax when we agree upon it.
I'm kinda bored anyways :)
All you will have to do when we change it is write a trivial script to convert the operator to its new syntax.
Assuming ?>
is unique enough, haha.
also add a <?rock operator, if you're to add ?> :P
Settled for $
for the moment, I've almost got working code right now, for some reason the replaced comma sequence doesn't get resolved at the moment.
@vendethiel
Sounds great and really convenient to inline ooc code into HTML, I will look into it! (/s, obviously :P)
All the code is on my forks at nagaqueen/safe_navigation and rock/safe_navigation if anyone is interested.
I wasn't resolving the root expression...
I nearly lost my mind debugging something that simple.
Seems to be working fine now!
Here is an example:
Bar: class {
baz: String
init: func (=baz)
}
Foo: class {
bar: Bar
init: func (=bar)
}
// Try this line out with null in different places
foo := Foo new(Bar new("yup"))
(foo $ bar $ baz ?? "nope") println()
There may be some little syntactic issues, the one I found right away is that this:
foo $ bar baz
Doesn't work.
Imho, you should be able to "break" the safe navigation at any point without parenthesis (although it really doesn't make sense to do so)
By the way @fasterthanlime, do you have issues with the syntax, or should I merge this into master once I've worked out the details and added some tests?
Imho, you should be able to "break" the safe navigation at any point without parenthesis (although it really doesn't make sense to do so)
What if you're trying to access covers inside an object? On that note, what should happen if you try to use the safe navigation operator on a cover?
@davidhesselbom
Rock will compile safe navigation expression blindly into exactly those things:
So (and I'm just guessing here) I think it would fail at C compiletime, because operator type checking is really sparse in rock (although I do think I remember seeing something about compatible pointer types in Comparison.ooc)
Also, what I mean when I say it doesn't really make much sense to break the safe navigation is that you are probably expecting the expression to return null, or at least you know there is a real possibility, so safe navigating somewhere and then blindly taking a member seems like suicide.
I do think this is a bug though and I will fix nagaqueen to make such accesses possible without parentheses.
Well, just because foo
is likely to be null doesn't mean that bar
or baz
are likely to (if foo
isn't null). It doesn't seem like suicide to me any more than do all the other times you use an object.
Ah, I see what you're saying now, I am indeed mistaken.
That's what happens when I answer to posts 5 minutes after I wake up without having drunk my coffee _
Covers do fail with a nice error message " Invalid comparison between operands of type Foo and Pointer", I am pleasantly surprised.
Good :)
Still,
Foo: class {
x: Float
init: func (=x)
}
foo: Foo = null
y := foo $ x
What should happen here? What type is y
and what is its value?
y should be set to null
The expression is translated to:
Foo: class { ... }
foo: Foo = null
safeNav1 : Foo
y := (safeNav1 = foo, foo != null ? foo x : null)
Oooh, wrong again I guess.
This doesn't compile because Float and null are incompatible but this is something we can't work around, cover vs class havs always been a weird part of the ooc typesystem.
What if we don't know at compile time whether foo
is null?
I should probably make it a nice error though, " Using different types in a ternary expression is forbidden. Find another way :)" doesn't really tell us anything in this case.
Okay, so, basically, this will never work if you want the result to be a cover, unless ooc starts supporting nullable types? What about...
Foo: class {
bar: Bar
init: func (=bar)
}
Bar: cover {
baz: String
init: func (=baz)
}
foo: Foo = null
y := foo $ bar baz
Would this work?
This could work with a little trickery and a lot of nagaqueen hacking (as well as restarting the safe navigation after baz), I will be taking a look later today.
@davidhesselbom
This works in my local copy, pushing to my branch in a while
Bar: cover {
baz: String
init: func@ (=baz)
}
Foo: class {
bar: Bar
init: func (=bar)
}
bar: Bar
bar init("yoyoyo")
foo := Foo new(bar)
y := foo $ bar baz $ _buffer
if (y) {
y toString() println()
}
Changes on shamanas:rock/safe_navgation, shamanas:nagaqueen/safe_navigation.
I think we should use the following syntax:
a ¯\_(ツ)_/¯ b ¯\_(ツ)_/¯ c
(In all seriousness, I have no idea what actually makes sense here, and I'm not sure I'm actually fond of the idea itself. It sounds like something useful mostly for dynamic languages, and I'm pretty sure it just helps hides a lot of programmer error rather than actually solve anything)
Well, the better solution would be non-nullable types and/or an architecture where null NEVER appears but there are bound to be places in your code were null appears and you need to navigate into some class.
For example, navigating rock's AST, something like expr $ type ?? voidType
, where an expression is optional and we should default to void, things like that.
Of course, this is your language after all and if you dislike the feature, I can just close the issue, the PRs and never talk about this again :)
I don't think blocking one more feature is going to make or break the language at this point.. if it's already working, I suppose $
is good enough for now.
The only downside is that someone might come up with a better syntax someday, change it, and break existing code. Not that a lot would have to be fixed even then...
@davidhesselbom It will be merged soon, after I finish class templates so I don't mess up the grammar.
If I don't finish those today or tomorrow morning, I will be merging it alone tomorrow afternoon.
Description of the C# safe navigation operator ?. provided by @davidhesselbom