digitalmars.D - Where should I put a `condp` like function?
- Idan Arye (16/16) Apr 14 2013 I'm replicating `condp` from
- bearophile (4/5) Apr 14 2013 I think you should explain why you think it's useful.
- Idan Arye (18/23) Apr 14 2013 Well, `predSwitch` has two main advantages on regular `switch`.
- bearophile (6/8) Apr 14 2013 In various Reddit threads I see people almost angry against the
- Nick Sabalausky (7/16) Apr 14 2013 I've never seen a big problem with the statement vs expression
- H. S. Teoh (34/50) Apr 14 2013 [...]
- Nick Sabalausky (4/24) Apr 15 2013 Yup, like I said, I've definitely wished that D's switch could be used
- Nick Treleaven (5/15) Apr 17 2013 We could use a conditional operator chain:
- Idan Arye (16/35) Apr 15 2013 Having D's `switch` be an expression is problematic, since D does
- Nick Sabalausky (14/27) Apr 15 2013 Wouldn't it be possible to just simply choose between these two forms
- Idan Arye (9/38) Apr 15 2013 Possible? probably. Simply? probably not. `switch` is already a
- Nick Sabalausky (7/12) Apr 15 2013 I'm not a Phobos dev, but I think std.algorithm would be the right
- H. S. Teoh (7/17) Apr 15 2013 [...]
- Nick Sabalausky (5/21) Apr 15 2013 Yea, but the same is true for a lot of std.algorithm. Besides, despite
- Idan Arye (4/30) Apr 15 2013 Actually, std.functional only has two functions that turn a
- David Gileadi (2/3) Apr 16 2013 It's this kind of joke where I draw the line :)
- Idan Arye (6/20) Apr 15 2013 Good idea. It's not really an algorithm - but then again, many of
- Timon Gehr (3/17) Apr 16 2013 I do not see how std.monad would be an accurate name in any case.
- Graham Fawcett (5/11) Apr 18 2013 Nit-picky observation: there's nothing monadic about your
- Idan Arye (14/26) Apr 18 2013 A monad is "a structure that represents computations"(quote from
- Timon Gehr (2/18) Apr 18 2013 Read on.
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?
Apr 14 2013
Idan Arye:(because it's a useful function)I think you should explain why you think it's useful. Bye, bearophile
Apr 14 2013
On Sunday, 14 April 2013 at 23:54:57 UTC, bearophile wrote:Idan Arye: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`.(because it's a useful function)I think you should explain why you think it's useful. Bye, bearophile
Apr 14 2013
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
Apr 14 2013
On Mon, 15 Apr 2013 02:48:27 +0200 "bearophile" <bearophileHUGS lycos.com> wrote:Idan Arye: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.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.
Apr 14 2013
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:[...] 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.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.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.
Apr 14 2013
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:Yup, like I said, I've definitely wished that D's switch could be used as an expressionI'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; }; }
Apr 15 2013
On 15/04/2013 06:00, H. S. Teoh wrote: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; }; }We could use a conditional operator chain: image[x,y] = isFillable(image,x,y) ? fillColor : isBorder(image,x,y) ? borderColor : defaultColor;
Apr 17 2013
On Wednesday, 17 April 2013 at 13:09:45 UTC, Nick Treleaven wrote:On 15/04/2013 06:00, H. S. Teoh wrote:Naturally - even as statements, a `switch` statement without a switch expression is no better than a chain of `if`-`else`s. Now, consider this hackish use of `predSwitch`: https://gist.github.com/someboddy/5412843 This is actual D code(you need https://github.com/D-Programming-Language/phobos/pull/1259 to run it), and it prints: ***** *...* *.+.* *...* ***** As expected. This does have an advantage over a chain of `if`-`else`s or ternary operators - you only need to write the argument list once.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; }; }We could use a conditional operator chain: image[x,y] = isFillable(image,x,y) ? fillColor : isBorder(image,x,y) ? borderColor : defaultColor;
Apr 18 2013
On Thursday, 18 April 2013 at 13:58:46 UTC, Idan Arye wrote:Naturally - even as statements, a `switch` statement without a switch expression is no better than a chain of `if`-`else`s.As mentioned before in other thread, LLVM is crazy good at transforming if/else chains into switch statement, and GCC does a good job at it as well.
Apr 18 2013
On Thursday, 18 April 2013 at 14:26:08 UTC, deadalnix wrote:On Thursday, 18 April 2013 at 13:58:46 UTC, Idan Arye wrote:A `switch` statement is faster than a `if`-`else` chain only when it can use a lookup table, and for the lookup table a switch expression is a must. Another precondition for a lookup table is that the test expressions are known at compile-time. The given example has none - there is no switch expression(though one may argue that you can use `true` as the switch expression) and the test expressions are function calls calculated at runtime. If the compiler can translate a `if`-`else` chain to a `switch` statement - then it should have probably been a `switch` statement in the first place. That way it would have also been more readable.Naturally - even as statements, a `switch` statement without a switch expression is no better than a chain of `if`-`else`s.As mentioned before in other thread, LLVM is crazy good at transforming if/else chains into switch statement, and GCC does a good job at it as well.
Apr 18 2013
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: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...Idan Arye: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.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.
Apr 15 2013
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...]; ... }
Apr 15 2013
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: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.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...]; ... }
Apr 15 2013
On Mon, 15 Apr 2013 01:52:33 +0200 "Idan Arye" <GenericNPC gmail.com> wrote: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?I'm not a Phobos dev, but I think std.algorithm would be the right place. You can always just pick a spot, make a pull request, and if there's a better place then people can just say so in the pull request's discussion and then you can move it.
Apr 15 2013
On Mon, Apr 15, 2013 at 02:01:28PM -0400, Nick Sabalausky wrote:On Mon, 15 Apr 2013 01:52:33 +0200 "Idan Arye" <GenericNPC gmail.com> wrote:[...] Hmm. What about std.functional? It seems to fall into the category of stuff that lets/helps you write functional-style D code. T -- Without geometry, life would be pointless. -- VSbut 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?I'm not a Phobos dev, but I think std.algorithm would be the right place.
Apr 15 2013
On Mon, 15 Apr 2013 11:05:05 -0700 "H. S. Teoh" <hsteoh quickfur.ath.cx> wrote:On Mon, Apr 15, 2013 at 02:01:28PM -0400, Nick Sabalausky wrote:Yea, but the same is true for a lot of std.algorithm. Besides, despite the name, std.functional appears to mostly just be the place for the tools to use the old string literal style lambdas.On Mon, 15 Apr 2013 01:52:33 +0200 "Idan Arye" <GenericNPC gmail.com> wrote:[...] Hmm. What about std.functional? It seems to fall into the category of stuff that lets/helps you write functional-style D code.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?I'm not a Phobos dev, but I think std.algorithm would be the right place.
Apr 15 2013
On Monday, 15 April 2013 at 18:30:26 UTC, Nick Sabalausky wrote:On Mon, 15 Apr 2013 11:05:05 -0700 "H. S. Teoh" <hsteoh quickfur.ath.cx> wrote:Actually, std.functional only has two functions that turn a string to a function. Most of std.functional's members are for creating functions from other functions.On Mon, Apr 15, 2013 at 02:01:28PM -0400, Nick Sabalausky wrote:Yea, but the same is true for a lot of std.algorithm. Besides, despite the name, std.functional appears to mostly just be the place for the tools to use the old string literal style lambdas.On Mon, 15 Apr 2013 01:52:33 +0200 "Idan Arye" <GenericNPC gmail.com> wrote:[...] Hmm. What about std.functional? It seems to fall into the category of stuff that lets/helps you write functional-style D code.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?I'm not a Phobos dev, but I think std.algorithm would be the right place.
Apr 15 2013
On 4/15/13 11:05 AM, H. S. Teoh wrote:Without geometry, life would be pointless. -- VSIt's this kind of joke where I draw the line :)
Apr 16 2013
On Monday, 15 April 2013 at 18:02:14 UTC, Nick Sabalausky wrote:On Mon, 15 Apr 2013 01:52:33 +0200 "Idan Arye" <GenericNPC gmail.com> wrote:Good idea. It's not really an algorithm - but then again, many of the things in std.algorithm are not really algorithms, and could be easy fit to a separate module, called std.monad. Ofcourse, I do not suggest to split std.algorithm to std.algorithm and std.monad - that would break too much code...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?I'm not a Phobos dev, but I think std.algorithm would be the right place. You can always just pick a spot, make a pull request, and if there's a better place then people can just say so in the pull request's discussion and then you can move it.
Apr 15 2013
On 04/16/2013 04:39 AM, Idan Arye wrote:On Monday, 15 April 2013 at 18:02:14 UTC, Nick Sabalausky wrote:Well, given some obvious constraints on the inputs, they are.... I'm not a Phobos dev, but I think std.algorithm would be the right place. You can always just pick a spot, make a pull request, and if there's a better place then people can just say so in the pull request's discussion and then you can move it.Good idea. It's not really an algorithm - but then again, many of the things in std.algorithm are not really algorithms,and could be easy fit to a separate module, called std.monad. Ofcourse, I do not suggest to split std.algorithm to std.algorithm and std.monad - that would break too much code...I do not see how std.monad would be an accurate name in any case.
Apr 16 2013
On Sunday, 14 April 2013 at 23:52:37 UTC, Idan Arye wrote: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.Nit-picky observation: there's nothing monadic about your predSwitch function, it wouldn't belong in a 'std.monad' module. Best, Graham
Apr 18 2013
On Thursday, 18 April 2013 at 13:04:19 UTC, Graham Fawcett wrote:On Sunday, 14 April 2013 at 23:52:37 UTC, Idan Arye wrote:A monad is "a structure that represents computations"(quote from Wikipedia). While the Turing machine branch(=the main branch) of computability theory quickly fell into the Turing tarpit and had to moved to pseudo-code, the Lambda calculus was expended using the traditional mathematical method of defining symbols that replace other symbols. That's why when in the Turing machine branch you could just write `if ... then ... else ...` and it's okay because it's pseudo-code, in Lambda calculus you actually have an IFTHENELSE defined as a lambda expression. And so on with loops, exception handling, and even type definitions and input/output. I find that `predSwitch` - a function that represents the `switch` idiom - perfectly fits into the definition of monads.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.Nit-picky observation: there's nothing monadic about your predSwitch function, it wouldn't belong in a 'std.monad' module. Best, Graham
Apr 18 2013
On 04/18/2013 04:18 PM, Idan Arye wrote:On Thursday, 18 April 2013 at 13:04:19 UTC, Graham Fawcett wrote:Read on.On Sunday, 14 April 2013 at 23:52:37 UTC, Idan Arye wrote:A monad is "a structure that represents computations"(quote from Wikipedia). ...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.Nit-picky observation: there's nothing monadic about your predSwitch function, it wouldn't belong in a 'std.monad' module. Best, Graham
Apr 18 2013
On Thursday, 18 April 2013 at 17:12:51 UTC, Timon Gehr wrote:On 04/18/2013 04:18 PM, Idan Arye wrote:OK, so it's not a formal monad, but it has the same idea of - "an action that chooses the next action based on the results of previous actions" - for the same purpose - "insert additional operations around a program's domain logic".On Thursday, 18 April 2013 at 13:04:19 UTC, Graham Fawcett wrote:Read on.On Sunday, 14 April 2013 at 23:52:37 UTC, Idan Arye wrote:A monad is "a structure that represents computations"(quote from Wikipedia). ...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.Nit-picky observation: there's nothing monadic about your predSwitch function, it wouldn't belong in a 'std.monad' module. Best, Graham
Apr 19 2013
On Friday, 19 April 2013 at 19:02:51 UTC, Idan Arye wrote:OK, so it's not a formal monad, but it has the same idea of - "an action that chooses the next action based on the results of previous actions" - for the same purpose - "insert additional operations around a program's domain logic".Monad don't perform action. They describe an action to be performed by something else. Usually a lib or the runtime (as in Haskell).
Apr 19 2013
On Friday, 19 April 2013 at 19:05:10 UTC, deadalnix wrote:On Friday, 19 April 2013 at 19:02:51 UTC, Idan Arye wrote:Oh, I see. So I guess I got it wrong...OK, so it's not a formal monad, but it has the same idea of - "an action that chooses the next action based on the results of previous actions" - for the same purpose - "insert additional operations around a program's domain logic".Monad don't perform action. They describe an action to be performed by something else. Usually a lib or the runtime (as in Haskell).
Apr 19 2013