Thread overview | |||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
April 14, 2013 Where should I put a `condp` like function? | ||||
---|---|---|---|---|
| ||||
I'm replicating `condp` from Clojure(http://clojuredocs.org/clojure_core/1.2.0/clojure.core/condp). Basically, it's like a `switch` statement without lookup table, only it's an expression(so it returns a value) and you can choose your own predicate(the default will be "a == b"). For example: writeln(2.predSwitch!"a < b"( 1, "less then 1", 5, "less then 5", 10, "less then 10", "greater or equal to 10")); Now, I've got it working(the example actually compiles and prints "less then 5"), and I want to make a pull request to put it in Phobos(because it's a useful function) but I don't really know where to put it. None of the existing modules seems fit, and I don't want to open a new module(std.monad?) for a single function. Any suggestions? |
April 14, 2013 Re: Where should I put a `condp` like function? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Idan Arye | Idan Arye:
> (because it's a useful function)
I think you should explain why you think it's useful.
Bye,
bearophile
|
April 15, 2013 Re: Where should I put a `condp` like function? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Sunday, 14 April 2013 at 23:54:57 UTC, bearophile wrote:
> Idan Arye:
>
>> (because it's a useful function)
>
> I think you should explain why you think it's useful.
>
> Bye,
> bearophile
Well, `predSwitch` has two main advantages on regular `switch`. The first is being able to choose your own predicate. `switch` is preferable to a chain of `if`-`else if` because it's a clearer syntax(and because of the usage of lookup tables, but `predSwitch` does not have that), but not all `if`-`else if` chains are about simple equality checking - sometimes you need to check for other things, like which collection contains a value. Choosing your own predicate is helpful for that.
The second advantage - which I consider much more important - it that `predSwitch` returns a value. This means you can use it mid-expression - for example, to initialize a constant, or to determine a function argument. You can't do those things with `switch` because it's a statement. If you try to initialize a constant in a `switch` statement, the constant's scope will be limited to the `case` where it is defined, and if you want to use `switch` to determine a function argument, you're gonna have to write the rest of the function call in each `case`.
|
April 15, 2013 Re: Where should I put a `condp` like function? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Idan Arye | Idan Arye:
> You can't do those things with `switch` because it's a statement.
In various Reddit threads I see people almost angry against the statement-expression distinction in contemporary programming languages. I am just starting to understand them.
Bye,
bearophile
|
April 15, 2013 Re: Where should I put a `condp` like function? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Mon, 15 Apr 2013 02:48:27 +0200
"bearophile" <bearophileHUGS@lycos.com> wrote:
> Idan Arye:
>
> > You can't do those things with `switch` because it's a statement.
>
> In various Reddit threads I see people almost angry against the statement-expression distinction in contemporary programming languages. I am just starting to understand them.
>
I've never seen a big problem with the statement vs expression
distinction, and I think the "statements == expresions" languages
sometimes takes things slightly overboard in the process of forcing them
into the same mold. However, I've *definitely* wished on many
occasions that D's switch could be used as an expression like in Haxe.
|
April 15, 2013 Re: Where should I put a `condp` like function? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | On Sun, Apr 14, 2013 at 11:46:04PM -0400, Nick Sabalausky wrote: > On Mon, 15 Apr 2013 02:48:27 +0200 > "bearophile" <bearophileHUGS@lycos.com> wrote: > > > Idan Arye: > > > > > You can't do those things with `switch` because it's a statement. > > > > In various Reddit threads I see people almost angry against the statement-expression distinction in contemporary programming languages. I am just starting to understand them. [...] I think C was one of the early innovators in treating all function calls as expressions (or equivalently, allowing function calls to be statements). Many languages of that era differentiated between functions and procedures (== void functions), and treat calls to the latter strictly as statements. > I've never seen a big problem with the statement vs expression distinction, and I think the "statements == expresions" languages sometimes takes things slightly overboard in the process of forcing them into the same mold. However, I've *definitely* wished on many occasions that D's switch could be used as an expression like in Haxe. Allowing arbitrary predicates and switch-as-expression allows you to write code that shows intent very clearly: // In pseudo-D syntax void fill(T)(T image, int x, int y) { image[x,y] = switch { case isFillable(image,x,y): fillColor; case isBorder(image,x,y): borderColor; default: defaultColor; }; } This can help readability a lot when the outer expression is complicated. It's reminiscient of Dijkstra's guarded command language, which has a condition statement that contains a bunch of predicate-statement pairs; during execution, one statement is chosen from the conditional block whose predicate evaluates to true. At least one predicate must be true at any time, otherwise it is an error (similar to D's final switches). If more than one predicate evaluates to true, the choice is non-deterministic. The implementation can choose to provide a built-in uniform randomizer for this case. This lets you state the preconditions of statements up-front, thereby reducing mistakes caused by implicit assumptions that fail to hold. With code that is continually being revised, this can help prevent a lot of bugs. T -- Fact is stranger than fiction. |
April 15, 2013 Re: Where should I put a `condp` like function? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | On Monday, 15 April 2013 at 03:46:47 UTC, Nick Sabalausky wrote: > On Mon, 15 Apr 2013 02:48:27 +0200 > "bearophile" <bearophileHUGS@lycos.com> wrote: > >> Idan Arye: >> >> > You can't do those things with `switch` because it's a statement. >> >> In various Reddit threads I see people almost angry against the statement-expression distinction in contemporary programming languages. I am just starting to understand them. >> > > I've never seen a big problem with the statement vs expression > distinction, and I think the "statements == expresions" languages > sometimes takes things slightly overboard in the process of forcing them > into the same mold. However, I've *definitely* wished on many > occasions that D's switch could be used as an expression like in Haxe. Having D's `switch` be an expression is problematic, since D does not have the convention of blocks-returning-the-value-of-the-last-statement, and since D is statically typed - adding this might cause unwanted implicit conversions. Maybe it could be pulled off with a syntax similar to Scala: switch(x){ case 1 => ... case 2 => ... } This will also make it look similar to the function literal style, where using `=>` means you are gonna write the function's body as the return expression instead of as a block. In the meanwhile, we can use `predSwitch` - if I only knew where to put it... |
April 15, 2013 Re: Where should I put a `condp` like function? | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Sun, 14 Apr 2013 22:00:18 -0700
"H. S. Teoh" <hsteoh@quickfur.ath.cx> wrote:
> On Sun, Apr 14, 2013 at 11:46:04PM -0400, Nick Sabalausky wrote:
> > I've never seen a big problem with the statement vs expression distinction, and I think the "statements == expresions" languages sometimes takes things slightly overboard in the process of forcing them into the same mold. However, I've *definitely* wished on many occasions that D's switch could be used as an expression like in Haxe.
>
> Allowing arbitrary predicates and switch-as-expression allows you to write code that shows intent very clearly:
>
> // In pseudo-D syntax
> void fill(T)(T image, int x, int y) {
> image[x,y] = switch {
> case isFillable(image,x,y): fillColor;
> case isBorder(image,x,y): borderColor;
> default: defaultColor;
> };
> }
>
Yup, like I said, I've definitely wished that D's switch could be used as an expression
|
April 15, 2013 Re: Where should I put a `condp` like function? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Idan Arye | On Mon, 15 Apr 2013 18:41:07 +0200
"Idan Arye" <GenericNPC@gmail.com> wrote:
>
> Having D's `switch` be an expression is problematic, since D does not have the convention of blocks-returning-the-value-of-the-last-statement, and since D is statically typed - adding this might cause unwanted implicit conversions.
>
> Maybe it could be pulled off with a syntax similar to Scala:
> switch(x){
> case 1 => ...
> case 2 => ...
> }
>
Wouldn't it be possible to just simply choose between these two forms based on whether the switch is used where an expression is expected versus where a statement would be accepted?:
switch(cond) {
case 1: [...statements...] break;
...
}
vs
switch(cond) {
case 1: [...expression...];
...
}
|
April 15, 2013 Re: Where should I put a `condp` like function? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | On Monday, 15 April 2013 at 17:07:22 UTC, Nick Sabalausky wrote:
> On Mon, 15 Apr 2013 18:41:07 +0200
> "Idan Arye" <GenericNPC@gmail.com> wrote:
>>
>> Having D's `switch` be an expression is problematic, since D does not have the convention of blocks-returning-the-value-of-the-last-statement, and since D is statically typed - adding this might cause unwanted implicit conversions.
>>
>> Maybe it could be pulled off with a syntax similar to Scala:
>> switch(x){
>> case 1 => ...
>> case 2 => ...
>> }
>>
>
> Wouldn't it be possible to just simply choose between these two forms
> based on whether the switch is used where an expression is expected
> versus where a statement would be accepted?:
>
> switch(cond) {
> case 1: [...statements...] break;
> ...
> }
>
> vs
>
> switch(cond) {
> case 1: [...expression...];
> ...
> }
Possible? probably. Simply? probably not. `switch` is already a statement, so it will have to be added as an expression, but expressions in D can be used as statements, so it could create an ambiguity in the syntax parser - and those are seldom easy to solve.
The `switch`+`=>` solution should be simpler, since it doesn't create that ambiguity, but syntax additions are never that simple.
`predSwitch`, on the other hand, is dead simple.
|
Copyright © 1999-2021 by the D Language Foundation