Skip to content

Syntax for implicit conversion of output parameters, constrained parameters and adapting parameters #43

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
AndreVanDelft opened this issue Apr 23, 2016 · 8 comments

Comments

@AndreVanDelft
Copy link
Contributor

As for the syntax: I think these should just be syntactic sugar.
The preprocessor currently packs occurrences of ?a, ?a ?if(...) and ??a in ActualOutputParameter, ActualConstrainedParameter and ActualAdaptingParameter.
This is done when the expression is inside a script parameter list, not yet as terms in script expressions awaiting an implicit conversion. Well, I am not sure; I think that is not supported yet.

So with an implicit script key(??c: Int) we should be allowed to write:

key:?c
key:?c ?if isUppercase:c
key:??c (adapting parameter)

and with implicit conversions:

?c
?c ?if isUppercase:c
??c  
@AndreVanDelft
Copy link
Contributor Author

And ideally it should be possible to write ?c:Int and c:Int ?if (...)

This would also declare the local variable c, and make it visible in the rest of the sequence where this occurs (if there is no such sequence visible, then a sequence of length 1 is assumed).

@AndreVanDelft
Copy link
Contributor Author

?a: ActorRef ~~> s
t

Here the declared value a should not only be visible in t (see my previous comment),
but also in s.

@AndreVanDelft
Copy link
Contributor Author

The foregoing may be relatively easy to implement, except maybe for the requirement expressed in the previous section. To keep things simple, let's drop this requirement.

The main problem seems to be: what kind of variable declaration should this be equivalent with?
Distinguish the following cases:

  • LHS of dataflow arrow. ?a: A ~~> s is shorthand for [ var a: A = _; ?a ~~> s ]
  • In a sequence: x; ?a: A; y is shorthand for [ x; var a: A = _; ?a; y ]. Here x and y may be empty.

@AndreVanDelft
Copy link
Contributor Author

This test is a bit wrong:

  "Constrained params" should "work" in {
    implicit script param2script(??x: Int) = let x = 10

    script foo =
      var bar = 3
      ?bar ?if (bar > 0)
      ^bar

    foo.e shouldBe Success(10)    

Within param2script it should be possible to check that the formal parameter matches the actual one. This is done with FormalParameter.matches(value). Later, when the script call is about to succeed, the same test will be done again.
Note that at that point the formal parameter value has not yet been transferred to the actual parameter. In the code above bar is still 3. A slightly better test would be ?if (bar >= 10); this test would fail, which is in a way good, because it is wrong. The current test succeeds while it is wrong, and that is worse.
The test should not use the variable bar, but a placeholder: ?if (_ >= 10).

@AndreVanDelft
Copy link
Contributor Author

  "Output params" should "be usable from a script" in {
    implicit script param2script(?x: Int) = let x = 10

    script foo =
      var bar = 3
      ?bar
      ^bar

    foo.e shouldBe Success(10)
  }

This does not yet use the syntax ?a:T.
So the test (or a new test) should become:

  "Output params" should "be usable from a script" in {
    implicit script param2script(?x: Int) = let x = 10

    script foo =
      ?bar: Int
      ^bar

    foo.e shouldBe Success(10)
  }

@anatoliykmetyuk
Copy link
Contributor

"matches" is available from the implicit script. Can you please write a new
test or modify the existing one so that it tests the feature in question
and fails?
On May 13, 2016 11:16 PM, "André van Delft" notifications@github.com
wrote:

This test is a bit wrong:

"Constrained params" should "work" in {
implicit script param2script(??x: Int) = let x = 10

script foo =
  var bar = 3
  ?bar ?if (bar > 0)
  ^bar

foo.e shouldBe Success(10)

Within param2script it should be possible to check that the formal
parameter matches the actual one. This is done with
FormalParameter.matches(value). Later, when the script call is about to
succeed, the same test will be done again.
Note that at that point the formal parameter value has not yet been
transferred to the actual parameter. In the code above bar is still 3. A
slightly better test would be ?if (bar >= 10); this test would fail,
which is in a way good, because it is wrong. The current test succeeds
while it is wrong, and that is worse.
The test should not use the variable bar, but a placeholder: ?if (_ >= 10)
.


You are receiving this because you modified the open/close state.
Reply to this email directly or view it on GitHub
#43 (comment)

@AndreVanDelft
Copy link
Contributor Author

That should be like:

"Constrained params" should "work" in {

    var doesMatch = false
    var hadDeadlock = false

    implicit script param2script(??x: Int) = let {x = 1; doesMatch = _x.matches}

    script foo =
      var bar = 0
      do ?bar ?if (_ > 2) else let hadDeadlock=true
      ^bar

    foo.e shouldBe Success(0)
    doesMatch shouldBe false
    hadDeadlock shouldBe true

@AndreVanDelft
Copy link
Contributor Author

In C# 7.0 such parameters will be called "out variables". We may learn from those:

Out variables

Currently in C#, using out parameters isn’t as fluid as we’d like. Before you can call a method with out parameters you first have to declare variables to pass to it. Since you typically aren’t initializing these variables (they are going to be overwritten by the method after all), you also cannot use var to declare them, but need to specify the full type:

public void PrintCoordinates(Point p)
{
    int x, y; // have to "predeclare"
    p.GetCoordinates(out x, out y);
    WriteLine($"({x}, {y})");
}

In C# 7.0 we are adding out variables; the ability to declare a variable right at the point where it is passed as an out argument:

public void PrintCoordinates(Point p)
{
    p.GetCoordinates(out int x, out int y);
    WriteLine($"({x}, {y})");
}

Note that the variables are in scope in the enclosing block, so the subsequent line can use them.

Most kinds of statements do not establish their own scope, so out variables declared in them are usually introduced into the enclosing scope.

Note: In Preview 4, the scope rules are more restrictive: Out variables are scoped to the statement they are declared in. Thus, the above example will not work until a later release.

Since the out variables are declared directly as arguments to out parameters, the compiler can usually tell what their type should be (unless there are conflicting overloads), so it is fine to use var instead of a type to declare them:

p.GetCoordinates(out var x, out var y);

A common use of out parameters is the Try... pattern, where a boolean return value indicates success, and out parameters carry the results obtained:

public void PrintStars(string s)
{
    if (int.TryParse(s, out var i)) { WriteLine(new string('*', i)); }
    else { WriteLine("Cloudy - no stars tonight!"); }
}

Note: Here i is only used within the if-statement that defines it, so Preview 4 handles this fine.

We plan to allow “wildcards” as out parameters as well, in the form of a *, to let you ignore out parameters you don’t care about:

p.GetCoordinates(out int x, out *); // I only care about x

Note: It is still uncertain whether wildcards make it into C# 7.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants