Comments (14)
I don't think 1 is what we should go for because it could lead to some confusion if you write this:
let assert Ok(_) = todo as "error message"
Here you can't really tell if as
is part of the first assertion or the todo
.
I think 3 would be the best choice if in the future we also want some kind of assert
keyword to support it as well in a similar way:
// 3.
assert as "wibble" [1, 2, 3] = list.reverse([3, 2, 1])
assert as "wibble" is_empty([])
let assert as "wibble" Ok(result) = maybe_fail()
If we went with 2, that means that if we ever decide to add assert
(on its own) the two ways to write it would look quite different and may be confusing:
let assert Ok(result) as "wibble" = maybe_fail()
// I don't think this looks particularly good and has the same problems as 1.
assert [1, 2, 3] = list.reverse([3, 2, 1]) as "now this is last"
// But having `assert as "wibble" [1, 2, 3] = list.reverse([3, 2, 1])`
// now would look quite different from 2. used when assigning to a variable
// here it comes after `assert` while in the other after the pattern
So that's my reasoning for preferring 3, and even if we never get an assert
keyword on its own I think it still looks slightly better π
from gleam.
@giacomocavalieri I think I agree with you.
However, I'm assuming in your code example you meant something akin to this?
- assert as "wibble" [1, 2, 3] = list.reverse([3, 2, 1])
+ assert as "wibble" [1, 2, 3] == list.reverse([3, 2, 1])
I assume assert
would just assert a boolean value in this case.
from gleam.
The as
keyword as a whole is one of the more confusing keywords in Gleam in my opinion. With its use in todo as "foo"
you can reasonably guess that the purpose of the string is to provide a label to the todo
keyword, and with panic as "foo"
you can possibly guess that the purpose of the string is to provide an error message to the panic
, but the keyword as
itself doesn't really do a good job at explaining anything about what the string is actually doing in either of those situations, so it's left up to the reader to deduce that via context.
With assert as "foo"
(regardless of where the as
actually ends up in the let assert
statement), the intention of the string following the as
is even less clear than the other two uses, and the as
keyword in this situation does nothing to aid in the understanding of what the string might be for. Is it checking that string against something as part of the assertion? Or doing something else with the string? For new users of the language, I think this will be pretty confusing to read.
The issue that needs to be solved is being able to provide extra data to certain keywords, preferably in a way that makes it clear what the data being provided is (like with a labelled function arg), but without having the syntax be confused with a function call.
As a potential solution to this issue (or at least what I believe is an issue), I propose the following alternative to the as
syntax, that can replace the current usage of as
in its current use with todo
, panic
and be used in the future with assert
:
todo #label="foo"
panic #error_message="foo"
assert #error_message="foo"
// whitespace should be supported everywhere except for after # to avoid parsing
// confusion with tuples or user confusion with comment syntax in other languages
todo #label = "foo"
// if a keyword supports more than one data item, they can be provided like so
todo #label="foo" #description="more detailed info"
The syntax is inspired by url query params (which helps to reinforce that they're optional attributes, not required ones). The language server should ideally show the available attributes that can be provided when hovering over a keyword, similar to a function signature (though distinct enough to avoid confusion).
I believe the only place the #
symbol is used currently is in tuples, and for those it is required to be followed by either whitespace or a (
, whereas in this situation it will always be followed by a name/identifier (which cannot include (
or whitespace), so determining which it is in the parser should not be too difficult I imagine.
It might also be worth considering allowing this syntax to occur anywhere on the same line as a supported keyword for the purposes of keeping the main body of the line clean, such as with the following:
let assert Ok(foo) = returns_result() #error_message="got an Error instead of Ok"
It would basically act as a comment, except it would be passed as context to any keywords on that line. Any attributes that don't apply to a particular keyword can just be discarded when passed to it, which allows for lines containing multiple keywords to still receive their respective data:
let assert Ok(foo) = todo #error_message="got an Error instead of Ok" #label="add code that returns a Result"
Interested to know what others think of this suggestion, or if anyone has any other suggestions for the syntax of something like this.
from gleam.
I've never seen as
as confusing, it's really interesting to hear other's opinions about it!
Personally, I don't think that the labels make it any clearer than as
: moving the error message at the end of the line away from the assert
doesn't make it clearer, with as
next to assert
I immediately can tell that that's the assertion's error message and I don't have to skim through to the end of the line to see if it has any extra label attached
from gleam.
If keeping the label close to the source of the keyword is a desired property, then only allowing the #attribute
right after the keyword could maybe be an option?
let assert#error_message="failed to match" Ok(foo) = returns_error()
from gleam.
I also don't see as
as a confusing thing. Like any keyword in any language, you have to learn its meaning, but once you've got it, it's fairly simple.
Also moving away from as
to an attribute-based system like you've described would be a breaking change, which would need a whole new version number. The way to prevent that would be to keep as
around, and I think having two bits of syntax for the same thing would arguably be even more confusing.
from gleam.
I think as
is ok-ish in its current usage for todo
and panic
, but assert as
is getting to the point where it's becoming confusing to read in my opinion, and if more keywords are ever added, as
is unlikely to really make sense from a readability standpoint for those either.
I understand the viewpoint of not wanting to introduce any more breaking changes though, so I'm not really sure how to improve the situation if anything breaking is off the table.
from gleam.
It's not really any different to languages that do assert predicate, "failure message"
, though I'd argue that's more confusing because in those languages (e.g. Python), x, y
could be a tuple.
from gleam.
It has to be as
, that is the established syntax for adding a message to a panic. We will not have a breaking change Ζor that so there's no point in discussing alternatives.
Hayleigh has pointed out on discord that let assert Ok(result) as "wibble" = maybe_fail()
is already valid syntax so we cannot use it here. This is unfortunate.
from gleam.
I am working on this right now :)
The main change would be:
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AssertAssignment<ExpressionT> {
pub location: SrcSpan,
pub message: Option<Box<ExpressionT>>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Assignment<TypeT, ExpressionT> {
pub location: SrcSpan,
pub value: Box<ExpressionT>,
pub pattern: Pattern<TypeT>,
pub assert: Option<Box<AssertAssignment<ExpressionT>>>,
pub annotation: Option<TypeAst>,
}
from gleam.
Implementation won't be too complex but we haven't landed on a design yet, I would wait until we decide what this should look like or the PR might not get merged as of now
from gleam.
I will send a prototype with the 3.
option. Since 2.
is already doing something else.
And 1.
looks very different from the current todo as ""
and panic as ""
cases.
It can always be closed if some other option is a better fit. For me this is just a good way to learn the internals of this compiler :)
from gleam.
How would it work with the upcoming assert x != y
syntax? How would as
work there?
from gleam.
@lpil sorry, I couldn't find the new assert
spec anywhere, so I might be missing something. Generally assert as "x is not equal to y" x != y
seems fine to me. In this case it would use this as a base message, while it also should show what x
and y
was in the error's context.
from gleam.
Related Issues (20)
- Prefixed ints require brackets to be negated HOT 1
- LSP: Show module docs when hovering a module HOT 6
- Lucy is not rotating on site HOT 1
- LSP: Add local variable suggestions HOT 1
- LSP: Goto Definition not working properly for unqualified imports HOT 2
- (hex)docs: types in function signatures should be clickable links to their documentation HOT 1
- Deprecate `..` discard if not preceded by a comma HOT 1
- Improve the error message for using module alias as a name HOT 2
- LSP code action: turn (wrong) C-style type definition into a single constructor type HOT 1
- Gleam package manager seems to default to oldest possible version instead of most recent HOT 1
- Language Server: Label access completion only works with public types
- `gleam export package-interface` breaks when build is cached HOT 3
- lsp crash HOT 1
- gleam doesn't update, on AUR helper (yay) HOT 3
- Infer minimum Gleam version HOT 5
- Allow Strings in a BitArray literal without having to specify utf8 encoding HOT 3
- Print progress to stderr, not stdout HOT 3
- LSP: autocompleting type imports should add brackets if needed HOT 1
- string.drop_left appears to return array of ASCII codes in some circumstances HOT 2
- Inconsistency with tag name format expected for source links in docs based on repository type HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from gleam.