winglang / wing

A programming language for the cloud ☁️ A unified programming model, combining infrastructure and runtime code into one language ⚡
https://winglang.io
Other
4.9k stars 194 forks source link

RFC: Type/namespace aliases #3350

Open eladb opened 1 year ago

eladb commented 1 year ago

Feature Spec

The let statement can be used to create aliases for types and namespaces in Wing:

bring "aws-cdk-lib" as aws;

let sfn = aws.aws_stepfunctions;
let tasks = aws.aws_stepfunctions_tasks;
let StateMachine = sfn.StateMachine;

let submitJob = new tasks.LambdaInvoke(
  lambdaFunction: submitLambda,
  outputPath: "\$.guid",
) as "Submit Job";

let waitX = new sfn.Wait(
  time: sfn.WaitTime.secondsPath("\$.waitSeconds"),
) as "Wait X Seconds";

let getStatus = new tasks.LambdaInvoke(
  lambdaFunction: getStatusLambda,
  inputPath: "\$.guid",
  outputPath: "\$.status",
);

let jobFailed = new sfn.Fail(
  cause: "AWS Batch Job Failed",
  error: "DescribeJob returned FAILED",
) as "Job Failed";

let finalStatus = new tasks.LambdaInvoke(
  lambdaFunction: getStatusLambda,
  inputPath: "\$.guid",
  outputPath: "\$.Payload",
) as "Get Final Job Status";

new StateMachine(
  timeout: 5m,
  definition: submitJob
    .next(waitX)
    .next(getStatus)
    .next(
      new sfn.Choice(this, "Job Complete?")
        .when(sfn.Condition.stringEquals("$.status", "FAILED"), jobFailed)
        .when(sfn.Condition.stringEquals("$.status", "SUCCEEDED"), finalStatus)
        .otherwise(waitX)
    )
);

Language Design Rationale

I am thinking of let as a tool for assigning names to things. I don't see a good reason why I can't use it to give namespaces and types names as well.

The alternative I considered is some convoluted syntax related to bring, but I truly don't see a good reason not our existing language constructs without inventing new ones.

(Inspired from Zig)

Use Cases

Just imagine how this code above will look like without these aliases.

Implementation Notes

No response

Component

Language Design

Community Notes

Chriscbr commented 1 year ago

I'm cool with the idea. I'd just add that adding a syntax for bringing specific types/namespaces from an import also just seems like a nice thing to have. For example

bring "my-wing-library" as mylib;

let module1 = mylib.module1;
let module2 = mylib.module2;
let Type1 = mylib.Type1;

would look cleaner to me as:

bring module1, module2, Type1 from "my-wing-library";

I think the choice to use let is kind of a syntax bike-shedding topic, so we probably shouldn't dwell on it too much, but for sake of proposing alternatives for comparison, any of these would also get the job done.

bring sfn from aws.aws_stepfunctions;
alias sfn as aws.aws_stepfunctions;
using sfn as aws.aws_stepfunctions;
type sfn = aws.aws_stepfunctions;

BTW, what would the error message look like when this source code is compiled?

let var StateMachine = sfn.StateMachine;
MarkMcCulloh commented 1 year ago

Inspired from Zig

It makes more sense in the context of zig because they don't have an import syntax at all (the intrinsic @import isn't really special). Unless we plan to get rid bring, I don't see an issue with making it more expressive.

I am thinking of let as a tool for assigning names to things. I don't see a good reason why I can't use it to give namespaces and types names as well.

Personally, I dislike the ambiguity. While reading code, I like when the syntax is able to prime me for what I see next. When I see let x = I know what follows will be a value. When my eyes are scanning a block of code, I know that any lets are introducing a new value binding. Broadening the meaning of let makes it less useful.

This signaling of intent is also great for IDEs. When you type let x = it will know some things it shouldn't show you because it knows what you're looking for. vice verse, type X = is now similarly useful and clear.

Chriscbr commented 1 year ago

This signaling of intent is also great for IDEs. When you type let x = it will know some things it shouldn't show you because it knows what you're looking for. vice verse, type X = is now similarly useful and clear.

Really good point

yoav-steinberg commented 1 year ago

I agree that for IDE's and humans this is clearer:

bring paleontology from "sciences";
type Species = paleontology.Species;
type Age = num;
let age = 10**6;
let dino = new Species(age);

I think it makes sense to use let for all of these if we're expanding what a variable is (making namespaces and types expressions):

bring "sciences" as sciences;
let var paleontology = sciences.paleontology;
let Dino  = paleontology.Dino;
bring "fantasy" as fantasy;
let fairy_tales = fantasy.fairy_tales;
let Dragon  = fairy_tales.Dragon;
assert(Dragon !=Dino);
let var convoluted_paleontology = paleontology;
convoluted_paleontology.props.add(Dragon.name, Dragon);

(:point_up: I'm against this, btw, but I also appreciate the value in it).

Final note: I think at some point we mentioned that

from "this" bring that; // is better than
bring that from "this"; // because of IDE completion issues (and mental model)
yoav-steinberg commented 1 year ago

BTW, what would the error message look like when this source code is compiled?

let var StateMachine = sfn.StateMachine;
  //^^^ types cannot be modified in wing (yet! muhahahaha)

And in the future:

let var TracedStateMachine = sfn.StateMachine;
TracedStateMachine.nextState = () => { 
  log("before moving to next state from ${this.current_state}");
  let orgNextState = sfn.StateMachine.bind(this);
  orgNextState();
  log("after moving to next state we're in ${this.current_state}");
};

(again, I'm against this. but...)

eladb commented 1 year ago

Eventually this is just the mental model people have about what let is. If it's a language construct for binding names to things, then I don't really see tons of value (either for humans or IDEs) in distinguishing between assigning names to namespaces, types or objects.

staycoolcall911 commented 1 year ago

We have discussed this on the second half of our team meeting (video). We decided we need someone to take this issue and expand the RFC with different use cases. We believe this will help us choose between the let and bring syntaxes proposed above.

Chriscbr commented 1 year ago

The latest proposal has been expanded in another issue: https://github.com/winglang/wing/issues/3352#issuecomment-1631053121

github-actions[bot] commented 11 months ago

Hi,

This issue hasn't seen activity in 60 days. Therefore, we are marking this issue as stale for now. It will be closed after 7 days. Feel free to re-open this issue when there's an update or relevant information to be added. Thanks!

github-actions[bot] commented 5 months ago

Hi,

This issue hasn't seen activity in 90 days. Therefore, we are marking this issue as stale for now. It will be closed after 7 days. Feel free to re-open this issue when there's an update or relevant information to be added. Thanks!

github-actions[bot] commented 2 months ago

Hi,

This issue hasn't seen activity in 90 days. Therefore, we are marking this issue as stale for now. It will be closed after 7 days. Feel free to re-open this issue when there's an update or relevant information to be added. Thanks!