In OCaml, you can even match exceptions, replacing try-catch:
match do_something () with
| Red(...) -> ...
| Black(...) -> ...
| exception Some_exn -> ...
I think in the case of OCaml the reason if and let are still around is just because they save characters, and they’re also more “precise” as to intention. Same reason we might have redundant forms in English.
This makes me think whether parts of the traditional try ... catch ... finally could also be subsumed by this (in Scala catch is already more or less a pattern match).
Author here, thought this might create some interesting discussion!
TL;DR:
Why have multiple distinct syntactic constructs for if-then-else, pattern matching and things like if-let, when they are largely doing the same thing (check some condition to make a decision on how the program should go on)?
The core idea is having a single, unified condition syntax that scales from simple one-liners to complex pattern matches that subsumes the existing syntax options.
k/q doesn’t use them very often, since it rarely makes things clearer. Function application is indexing, decode, projection and each-left, and so on, make it possible to write much less code.
for example, if x == 1.0 then "a" else "z" could be simply "za"1=
“one comparison operator on multiple targets” is: "zba"2 sv 1 2=\:
“different comparison operators, equality and identity” is: "zna"2 sv(1=;0w=)@\:
“method calls” are "zne"2 sv(isempty;0 in)@\:
Scala is an atom-language though. It can only do one thing at a time, so you see there to be a need to “check some condition to make a decision on how the program should go on” but, let’s say those lists are big, we can trivially parallelise “each”; In a data-parallel language, you very infrequently check some condition to make a decision on how the program should go on.
Computer languages need to strike a balance between human-language intuition and machine-parser explicitness. Simply slamming the slider all the way to the right isn’t a solution, so much as an admission of defeat, IMO.
My idea was totally different. I’ve noticed what people comprehend depends on their thinking style, background (esp prior languages), and so on. However, there’s fewer underlying concepts or structures in play than there are surface syntaxes or API’s. So, I was thinking that maybe languages should try multiple front-ends with different syntaxes, coding styles, etc. As a start, C and Python. Each client has a tool that automatically translates it to their style with same meaning.
Code that is shorter has a higher chance of being correct. If you can’t read it now, learning how to read it will make you a better programmer, and that benefits you, and everyone you work with.
Either indentation-based, or requiring some delimiter.
I’m largely in the indentation-based camp these days, so I haven’t spent much time thinking about how to make the delimitation to look nice. I’d probably just go with mandatory curly braces around the branches.
I think GHC’s MultiWayIf extension (and PatternGuards, which is just part of the base Haskell2010 standard now) gets you a unified condition syntax as well, although if you have a complicated discriminator you’ll want to bind it to a short name first to save yourself some typing.
(There is a difference in terminology here where what you call a pattern guard is just called a guard in Haskell land, and a pattern guard in Haskell is being able to use an arbitrary pattern match as a boolean condition and to bind variables in a (Haskell) guard.)
It’s a neat concept. It’s so weird to me since I’ve looked at the left, conditional, and right side of those all-together for years now. Just having the left alone on the top would take a bit of getting used to. :) Seriously, though, reading it made me think you should forward it to the Quorum people to see if they’ll do an experiment on it. You win if people find the new approach either better or the same. You win if it’s the same because it’s more symmetric and consistent than predecessors.
I have no idea. I just glanced at it a few times in the past. I remember reading PDF’s detailing their experiments on things like syntax. The concept was that any claim was tested empirically. If experiments showed it was better, then the feature or change went into the language. The place to start on it is here.
The problem is that Type ident syntax just doesn’t scale as soon as generics are involved, and by now I’d expect that every language has something like that.
What are your thoughts on expanding this to expression conditions where x is not the first item in the expression? Some examples that come to mind:
if 10 <= x (x on the right-hand side) (I personally like to arrange my comparisons from small to large, like a number line. That way the order of reading is also the order of size.)
if stdev(x) < 20 (compare some function of x)
if 11 <= x < 30 (x in a chained comparison)
if 12 <= x and (x % 2) (a compound expression that checks multiple properties of x)
Haven’t really thought about this, I’m slightly leaning against it, because it would introduce more complexity: the existing design is intentionally made the way it is, because it can be desugared at a syntactic level, without requiring typechecking or any other kind of semantic checks run first. (Not sure how important that is, though.)
This article makes me think about the difference between constructs where we have to impose an order on the checks and ones where we don’t. The latter seems nicer but they would lead us to drop ‘else’ and be explicit about the full decision space.
(where _ is “don’t care” placeholder). Internally, the compiler will [2] re-order the tests from “most-specific” to “least-specific” (so the _ , _ : bit is like ELSE). Also, here, getc() returns two values [3], both of which are checked. I do not have exceptions because I’m not fond of exceptions [5] so I don’t have syntax for it.
[1] Based off an idea I read about in the mid-80s [4].
[2] I’m still playing around with syntax.
[3] I had a hard time moving from assembly to C, simply because I could not return multiple values easily.
Non-existent. I’m still working (even after all these years) on syntax. It was only after I posed the above did I realize that trying to go from “most-specific” to “least-specific” is problematic in the above example. Of these two:
== EOF , _
!= 0 , _
Which one is more specific? It’s for these reasons (and some more) that this is taking a long time.
edit: I reread it, and think the idea of the partial conditional x == is OK for case like statements, and it seems my thought is actually still valid. Ok, then, wfm.
Interesting idea. Not sure that I like the short hand of the RHS of the conditional like that. Why not make it more generic and not require the LHS after the if? Then, it works by (conditional ‘then’ consequent)+ with an optional else alternate tacked on to the end? In this case you can mix conditionals that aren’t using the same LHS, though, I guess you end up missing out on case style conditionals…
If I have understood you correctly (please correct me if I’m wrong) is that you often want to check different things with the same LHS. The floating point example is probably not the best one, but I think it gets the issue across: Sometimes you want to check equality, sometimes you want to check identity (and sometimes you probably want to do both) for the same value.
My edited comment was poorly worded. My comment added nothing new after I reread. The syntax supports what I suggested, and case statements work with the partial LHS conditional. Basically, I support it. :)
In OCaml, you can even match exceptions, replacing try-catch:
I think in the case of OCaml the reason
ifandletare still around is just because they save characters, and they’re also more “precise” as to intention. Same reason we might have redundant forms in English.Wow, this is extremely helpful!
This makes me think whether parts of the traditional
try ... catch ... finallycould also be subsumed by this (in Scalacatchis already more or less a pattern match).Thanks for bringing this up!
Author here, thought this might create some interesting discussion!
TL;DR:
Why have multiple distinct syntactic constructs for if-then-else, pattern matching and things like if-let, when they are largely doing the same thing (check some condition to make a decision on how the program should go on)?
The core idea is having a single, unified condition syntax that scales from simple one-liners to complex pattern matches that subsumes the existing syntax options.
Are they the same?
Why do we even use if statements anyway?
k/q doesn’t use them very often, since it rarely makes things clearer. Function application is indexing, decode, projection and each-left, and so on, make it possible to write much less code.
for example,
if x == 1.0 then "a" else "z"could be simply"za"1=“one comparison operator on multiple targets” is:
"zba"2 sv 1 2=\:“different comparison operators, equality and identity” is:
"zna"2 sv(1=;0w=)@\:“method calls” are
"zne"2 sv(isempty;0 in)@\:Scala is an atom-language though. It can only do one thing at a time, so you see there to be a need to “check some condition to make a decision on how the program should go on” but, let’s say those lists are big, we can trivially parallelise “each”; In a data-parallel language, you very infrequently check some condition to make a decision on how the program should go on.
Your “simply” is my “incomprehensibly”.
Computer languages need to strike a balance between human-language intuition and machine-parser explicitness. Simply slamming the slider all the way to the right isn’t a solution, so much as an admission of defeat, IMO.
My idea was totally different. I’ve noticed what people comprehend depends on their thinking style, background (esp prior languages), and so on. However, there’s fewer underlying concepts or structures in play than there are surface syntaxes or API’s. So, I was thinking that maybe languages should try multiple front-ends with different syntaxes, coding styles, etc. As a start, C and Python. Each client has a tool that automatically translates it to their style with same meaning.
is it just me or does it sound like racket’s
#lang?Probably also not a coincidence that Racket is at the top of my list for a future project doing something similar. ;)
Your “intuition” is really mediocracy.
Code that is shorter has a higher chance of being correct. If you can’t read it now, learning how to read it will make you a better programmer, and that benefits you, and everyone you work with.
(laughs)
Downvote my thoughtful response as a troll, insult me, and then talk down to me. Really hit the internet trifecta, huh?
You’re the one who said you can’t comprehend something, and yet you believe you have something important to comment on it?
How is that not mediocrity?
Nice. I wonder how it works out grammatically for parser.
Either indentation-based, or requiring some delimiter.
I’m largely in the indentation-based camp these days, so I haven’t spent much time thinking about how to make the delimitation to look nice. I’d probably just go with mandatory curly braces around the branches.
I think GHC’s MultiWayIf extension (and PatternGuards, which is just part of the base Haskell2010 standard now) gets you a unified condition syntax as well, although if you have a complicated discriminator you’ll want to bind it to a short name first to save yourself some typing.
(There is a difference in terminology here where what you call a pattern guard is just called a guard in Haskell land, and a pattern guard in Haskell is being able to use an arbitrary pattern match as a boolean condition and to bind variables in a (Haskell) guard.)
It’s a neat concept. It’s so weird to me since I’ve looked at the left, conditional, and right side of those all-together for years now. Just having the left alone on the top would take a bit of getting used to. :) Seriously, though, reading it made me think you should forward it to the Quorum people to see if they’ll do an experiment on it. You win if people find the new approach either better or the same. You win if it’s the same because it’s more symmetric and consistent than predecessors.
Do they have some kind of log that shows their decision-making?
I have no idea. I just glanced at it a few times in the past. I remember reading PDF’s detailing their experiments on things like syntax. The concept was that any claim was tested empirically. If experiments showed it was better, then the feature or change went into the language. The place to start on it is here.
Not sure what their definition of quality is but just looking at https://quorumlanguage.com/tutorials/language/types.html seems it is even remotely in line with my expectations.
Did you notice the scalar types were close to how people describe things in problem descriptions? Looked pretty intuitive.
The problem is that
Type identsyntax just doesn’t scale as soon as generics are involved, and by now I’d expect that every language has something like that.What are your thoughts on expanding this to expression conditions where
xis not the first item in the expression? Some examples that come to mind:if 10 <= x(x on the right-hand side) (I personally like to arrange my comparisons from small to large, like a number line. That way the order of reading is also the order of size.)if stdev(x) < 20(compare some function of x)if 11 <= x < 30(x in a chained comparison)if 12 <= x and (x % 2)(a compound expression that checks multiple properties of x)Haven’t really thought about this, I’m slightly leaning against it, because it would introduce more complexity: the existing design is intentionally made the way it is, because it can be desugared at a syntactic level, without requiring typechecking or any other kind of semantic checks run first. (Not sure how important that is, though.)
This article makes me think about the difference between constructs where we have to impose an order on the checks and ones where we don’t. The latter seems nicer but they would lead us to drop ‘else’ and be explicit about the full decision space.
It looks similar to ideas I have as I work on my keywordless language [1]. A simple example would be:
(where
?isIF,:isTHENand^isRETURN). A more complex example is:(where
_is “don’t care” placeholder). Internally, the compiler will [2] re-order the tests from “most-specific” to “least-specific” (so the_ , _ :bit is likeELSE). Also, here,getc()returns two values [3], both of which are checked. I do not have exceptions because I’m not fond of exceptions [5] so I don’t have syntax for it.[1] Based off an idea I read about in the mid-80s [4].
[2] I’m still playing around with syntax.
[3] I had a hard time moving from assembly to C, simply because I could not return multiple values easily.
[4] It’s a long term PONARV of mine.
[5] It’s a dynamic GOTO and abused way too much in my opinion.
Very nice. Re [2], does that mean that the sequence of the checks in this construct really is immaterial?
Non-existent. I’m still working (even after all these years) on syntax. It was only after I posed the above did I realize that trying to go from “most-specific” to “least-specific” is problematic in the above example. Of these two:
Which one is more specific? It’s for these reasons (and some more) that this is taking a long time.
edit: I reread it, and think the idea of the partial conditional
x ==is OK for case like statements, and it seems my thought is actually still valid. Ok, then, wfm.Interesting idea. Not sure that I like the short hand of the RHS of the conditional like that. Why not make it more generic and not require the LHS after the if? Then, it works by
(conditional ‘then’ consequent)+with an optionalelse alternatetacked on to the end? In this case you can mix conditionals that aren’t using the same LHS, though, I guess you end up missing out oncasestyle conditionals…If I have understood you correctly (please correct me if I’m wrong) is that you often want to check different things with the same LHS. The floating point example is probably not the best one, but I think it gets the issue across: Sometimes you want to check equality, sometimes you want to check identity (and sometimes you probably want to do both) for the same value.
My edited comment was poorly worded. My comment added nothing new after I reread. The syntax supports what I suggested, and
casestatements work with the partial LHS conditional. Basically, I support it. :)