#List of questions/thoughts from Gleam Language Tour

1 messages · Page 1 of 1 (latest)

jovial tartan
#

I went through the Gleam Language Tour jotting down various small questions, things I wondered about or stuff I found somewhat weird/unclear there or in stdlib. All of the items are pretty minor: no showstoppers, just random bits and thoughts of someone new to the language (and somewhat new to the [typed] FP — my only previous experiences are some Elm in the recent past and some old Scala a long time ago).
Some may read as a bit blunt but it's not meant to criticize the language (I actually really liked it!) — they were meant as a list of questions or things to look up later for me.
Just thought maybe they may have some value for language/tour authors too?

#
  1. gleam/int & gleam/float:
    Why does divide return Error(Nil) when dividing by 0 instead of 0 (like /)?

  2. gleam/int:
    There is floor_divide in addition to divide. Why no ceil_divide (and maybe also round_division)?

  3. gleam/int:
    It might be nice to have a function for divison that simultaneously returns both modulo and reminder.

  4. gleam/float:
    Why does round return Int but floor and ceiling return Float?

  5. gleam/float:
    There is logarithm which is a natural logarith, but it seems like there is no something like logarithm_base(base: Float, of num: Float) (yes, I do know that formula).

  6. gleam/float:
    No trig functions in stdlib?!

  7. Tour/Floats:

Under the JavaScript runtime, exceeding the maximum (or minimum) representable value for a floating point value will result in Infinity (or -Infinity). Should you try to divide two infinities you will get NaN as a result.
So... how do I deal with NaN and Infinity in those cases? Those don't seem to be valid literals or type variants... I'm confused.

#
  1. Tour/Strings:
    Huh, it's pretty neat that I can just use single quotes even for multiline strings! Though it's a bit annoying that single quotes are the only option and there are no alternative syntax to avoid having to always escape quotes that are inside strings.
    Also it seems like multiline strings always treat indentation as actual content of the string but there is no stdlib function a-la Python's textwrap.dedent to automatically deal with that. Though I liked the way Swift dealt with it: it requires multiline strings to start on a new line and the closing quotes are used to mark the indentation level, so you can indent your multiline strings along with the rest of the code but all the spaces that are used purely for code indentation are omitted from the content of the string.
    Though I guess Swift-like behavior is still theoretically possible if Gleam chooses to add alternative string syntaxes (either for template strings or just to avoid \"), e.g. """...""" or something that looks more like blocks {"..."} (kinda like in djot).

  2. Tour/Strings:
    Tried to google how to do string interpolation or template string: apparently it's not possible (at least not yet, because there is a proposal).

  3. gleam/string:
    concat seems to have a copy-pasted section of docs from append:

This function copies both Strings and runs in linear time. If you find yourself joining Strings frequently consider using the string_tree module as it can append Strings much faster!
concat operates on an arbitrarily long list of strings not on "both". I assume they probably mean that it uses append over and over so the same issues apply?

  1. gleam/bool:
    Why is exclusive_* not shortened to x*? E.g. why is it exclusive_nor and not xnor or exclusive_negated_or?
#
  1. Tour/Type annotations:

Type annotations may be useful for documentation purposes, but they do not change how Gleam type checks the code beyond ensuring that the annotation is correct.
Maybe I misunderstand something, but I feel like they do change how Gleam type checks the code. For example, choosing to add/omit annotations and changing type parameters of phantom types changes whether the program typechecks or not.

  1. Tour/Type imports:
    Why is type keyword required when importing types? Is it to prevent some kinds of collisions? Isn't it obvious that the thing that's imported is a type since its name starts with a capital letter?

  2. Tour/Generic functions:

Type variables are not like an any type, they get replaced with a specific type each time the function is called.
Does this mean that they are not like any type in TypeScript, or is any a reserved special type in Gleam too?

  1. Tour/Labelled arguments:
    Initially I thought labelled arguments are similar to Swift's but there are no mandatory/optional labels (the language lets me completely omit any labels when calling a function), and it doesn't enforce the order of the arguments either, so they behave more like keyword arguments in Python (albeit with outward-facing labels). Not sure which approach I like more, but I do like that outward-facing labels are a thing. Gotta play more with that.

  2. Tour/Documentation comments
    Why is there an empty /// commented line above functions? Is it a convention?

  3. gleam/bool:
    There is int.random and float.random but no bool.random 🙁

  4. Tour/String patterns:
    It seems like I can match strings by prefix but not by suffix (question <> "?" -> ...) or both? That's unexpected. I wonder why?
    Also it would've been cool if I could use template strings for pattern matching.

#
  1. Tour/List patterns:
    Matching on list's ending like [.., 4] -> "Ends with 4" is not allowed too. I assume that's to discourage it because it's slow/list is the wrong data structure for doing that?

  2. Tour/Multiple subjects
    Is this the same as patter matching on tuples? Or is it possible to use some patters when matching tuples that are not restricted to exactly n patterns for an n-tuple? Or maybe it's the other way around?

  3. Tour/Alternative patterns:

Currently it is not possible to have nested alternative patterns, so the pattern [1 | 2 | 3] is not valid.
I like that it explicitly states it because that's exactly what I wanted to try to do.

  1. Tour/Guards:

Guard expressions cannot contain function calls, case expressions, or blocks.
The "or blocks" scared me a bit because I thought that stuff like [first, ...] if first > 2 * {limit + 1} wouldn't work. But it does!

  1. Tour/Tuples:
    Apparently I cannot match using #(first, ..rest) -> ... on tuples. I wonder why not?
    I still don't know if/how tuple pattern matching differs from multiple subjects.

  2. Tour/Records:
    Can records only exist withing a specific type variant? Are there no "general" records like Elm's {value: Type, other: OtherType}? If so I assume there are no things like extensible records either?

#
  1. Tour/Record accessors:
    This is a somewhat confusing paragraph:

The accessor syntax can always be used for fields with the same name that are in the same position and have the same type for all variants of the custom type. Other fields can only be accessed when the compiler can tell which variant the value is, such after pattern matching in a case expression.
I tried experimenting in the editor by adding additional id field to both variants but in differing positions and of different types:

pub type SchoolPerson {
  Teacher(name: String, id: String, subject: String)
  Student(id: Int, name: String)
}

...and I got no compile errors, echo still works printing both *.id values. Weird? Still not sure what exactly that paragraph actually meant.

  1. Tour/Record pattern matching:
    Starfish(name: String, favourite_color: String). Huh, I wonder if I finally encoutnered a programming language that actually settled on British spelling as the convention for naming things? Gotta check stdlib.

  2. Tour/Dict module:
    Why does the output of echoed dicts look so strange?


That's it

tepid nacelle
#
  1. So you can handle it as an error instead of 0
#
  1. no particular reason
#
  1. Nope. stdlib includes things that are very commonly used and maths generally going in maths packages
#
  1. Gleam doesn't have those
#
  1. Open an issue for this mistakes please 🙏
#
  1. We don't use cryptic abbreviations in Gleam. You may have learnt what that shorthand means, but that doesn't means other people know what it means
#
  1. Outside of record accessor use in some situations it does not change type checking. Using annotations for functions is recommended and standard though
#
  1. To know if you want to import from the type or value namespace. Values can start with capital letters too- custom type variants
#
  1. There is no any in Gleam
#
  1. Legibility, convention of the codebase
#
  1. I'm sure you can manage that implementation
#
  1. VM support, performance
#
  1. Pattern matching is fast, there's no literal syntax for slow things or for things we don't want to encourage. The language is designed to make the wrong thing harder to do than the right thing
#
  1. No, tuples are fixed length tuples, not variable length arrays
#
  1. Tuples are fixed length
#
  1. No ad hoc records. No extensible records.
#
  1. That's because the compiler knows which variant you're using in that context
#
  1. The BEAM ecosystem (Erlang, Elixir, Gleam, LFE, etc) uses British/Australian spelling due to being made by Brits and Aussies
#
  1. There's no literal syntax for dics. See also Haskell
jovial tartan
#

Wow, thank you so much for taking your time to answer those!

tepid nacelle
#

Some of those 😛

fringe wadi
#

favourite_color
🤔

#
  1. What happens in JS there will happen in Gleam, except there's no way to detect it in Gleam (this goes for both ints and floats). In case you want arbitrary precision integers in JS, you can use https://hexdocs.pm/bigi/index.html.
jovial tartan
# tepid nacelle 27. There's no literal syntax for dics. See also Haskell

Sorry, I'm not really sure what you meant here. I mean that in the Tour the output of echoing a dict looks like this //js(Dict { "root": //js({ "type": 2, "bitmap": -2138832896, "array": #(//js({ "type": 0, "k": "Darius", "v": 14 }), //js({ "type": 0, "k": "Bushra", "v": 16 }), //js({ "type": 0, "k": "Lucy", "v": 13 })) }), "size": 3 })

#

Instead of being a list of key-value tuples or something like that

lilac frigate
#

Oh yeah that's a bug. The intended syntax is dict.from_list([#(key, value), #(key, value)])

#

Seems like this has something to do with the wasm compiler specifically? Or using a browser. It works fine when I run it on my machine

jovial tartan
#

Oh, I see

jovial tartan
tepid nacelle
#

oh weird

#

What's going on there....

#

Could you open an issue for that please

jovial tartan
#

The issue for the echo dict?

tepid nacelle
#

Yup

lilac frigate
jovial tartan
#

Should I raise it in gleam-lang/gleam or gleam-lang/playground (if that's what powers the Tour)? (it is reproduced in playground)

tepid nacelle
#

playground sounds good

jovial tartan
sour mortar
#

26 is funny to me because it uses the american 'color'

tepid nacelle
#

oh yes