Skip to content
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

Builtins to implement #664

Open
25 of 50 tasks
rtfeldman opened this issue Nov 8, 2020 · 21 comments
Open
25 of 50 tasks

Builtins to implement #664

rtfeldman opened this issue Nov 8, 2020 · 21 comments
Labels
P-high High priority/frequency

Comments

@rtfeldman
Copy link
Sponsor Contributor

rtfeldman commented Nov 8, 2020

Builtins to implement

These are some builtins we haven't yet implemented. When implementing a builtin, please:

  1. Make an issue for it and and assign it to yourself so no one accidentally starts implementing your builtin after you've started!
  2. Put all the necessary changes for adding your builtin in the same PR, with no extraneous changes unrelated to adding the builtin. Then, include the name of the module and builtin (for example, List.dropAt) in the title of the PR. This allows other contributors to find your PR later and use it as an example when they are trying to implement their first builtins.

Num

  • maxU128 : U128
  • toI8 : Int * -> I8
  • toI16 : Int * -> I16
  • toI32 : Int * -> I32
  • toI64 : Int * -> I64
  • toI128 : Int * -> I128
  • toU8 : Int * -> U8
  • toU16 : Int * -> U16
  • toU32 : Int * -> U32
  • toU64 : Int * -> U64
  • toU128 : Int * -> U128
  • toF32 : Num * -> F32
  • toF64 : Num * -> F64
  • parseI16 : List U8, Endi, Nat -> Result I16 [ NotEnoughBytes ]*
  • parseU16 : List U8, Endi, Nat -> Result U16 [ NotEnoughBytes ]*
  • parseI32 : List U8, Endi, Nat -> Result I32 [ NotEnoughBytes ]*
  • parseU32 : List U8, Endi, Nat -> Result U32 [ NotEnoughBytes ]*
  • parseI64 : List U8, Endi, Nat -> Result I64 [ NotEnoughBytes ]*
  • parseU64 : List U8, Endi, Nat -> Result U64 [ NotEnoughBytes ]*
  • parseI128 : List U8, Endi, Nat -> Result I128 [ NotEnoughBytes ]*
  • parseU128 : List U8, Endi, Nat -> Result U128 [ NotEnoughBytes ]*
  • parseF32 : List U8, Endi, Nat -> Result F32 [ NotEnoughBytes ]*
  • parseF64 : List U8, Endi, Nat -> Result F64 [ NotEnoughBytes ]*
  • parseNat : List U8, Endi, Nat -> Result Nat [ NotEnoughBytes ]*
  • parseDec : List U8, Endi, Nat -> Result Dec [ NotEnoughBytes ]*

List

Result

  • map2 : Result a err, Result b err, (a, b -> c) -> Result c err
  • map3 : Result a err, Result b err, Result c err, (a, b, c -> d) -> Result d err
  • map4 : Result a err, Result b err, Result c err, Result d err, (a, b, c, d -> e) -> Result e err
  • map5 : Result a err, Result b err, Result c err, Result d err, Result e err, (a, b, c, d, e -> f) -> Result f err
  • map6 : Result a err, Result b err, Result c err, Result d err, Result e err, Result f err, (a, b, c, d, e, f -> g) -> Result g err
  • map7 : Result a err, Result b err, Result c err, Result d err, Result e err, Result f err, Result g err, (a, b, c, d, e, f, g -> h) -> Result h err
  • map8 : Result a err, Result b err, Result c err, Result d err, Result e err, Result f err, Result g err, Result h err, (a, b, c, d, e, f, g, h -> i) -> Result i err
  • mapBoth : Result ok1 err1, (ok1 -> ok2), (err1 -> err2) -> Result ok2 err2
  • try : Result before err, (before -> Result after err) -> Result after err
  • onErr : Result ok before, (before -> Result ok after) -> Result ok after
  • isOk : Result * * -> Bool #1954
  • isErr : Result * * -> Bool #1965

Str

This was referenced Dec 20, 2020
@rtfeldman rtfeldman pinned this issue Dec 22, 2020
This was referenced Dec 23, 2020
@Chadtech
Copy link
Contributor

Chadtech commented Mar 18, 2021

Are any of these functions worth including in List?

I've been maintaining elm-community/list-extra over the years, Ive gotten to see which List.Extra functions Elm people seem to like. Here are the "all stars" of List.Extra imo; the functions that seem to get a lot of use and attention:

unique : List elem -> List elem
uniqueBy : List elem, (elem -> Str) -> List elem

group : List elem -> List { first : elem, rest : List elem }
groupWhile : List elem, (elem -> elem -> Bool) -> List { first : elem, rest : List elem }

# groupsOf [ 1, 2, 3, 4, 5, 6, 7 ] 3 == [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]
groupsOf : List elem, Int -> List (List elem)

# greedyGroupsOf [ 1, 2, 3, 4, 5, 6, 7 ] 3 == [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7 ] ]
greedyGroupsOf : List elem, Int -> List (List elem)

List.Extra is by definition the functions that didn't make the cut into Elm, so I could understand if thats the case in Roc too. Maybe now is a good time to re-evaluate.

@rvcas rvcas unpinned this issue Apr 11, 2021
@rtfeldman rtfeldman pinned this issue Oct 10, 2021
@rtfeldman rtfeldman mentioned this issue Oct 25, 2021
4 tasks
@matthiasbeyer
Copy link
Contributor

divFloor is already implemented in compiler/builtins/src/std.rs

@Giesch
Copy link
Contributor

Giesch commented Oct 28, 2021

I've got a PR out for Str.trim. I could add trimLeft and trimRight after that, or leave those as nice intro issues. It would be nice to implement trim in terms of trimLeft and trimRight, or all three of those and dropPrefix/dropSuffix in terms of compiler-private Roc functions.

@rtfeldman
Copy link
Sponsor Contributor Author

@Giesch if you want to go for trimLeft and trimRight, I'd say go for it! I think Str.trim can be faster if it's not implemented in terms of trimLeft and trimRight though, so I'd leave that as-is! 😄

@iacore
Copy link
Contributor

iacore commented Nov 10, 2021

Is it necessary to include Str, Dict and Set as builtin? All three types can be implemented in Roc with List and Num.

I'd say make them part of the standard library written in Roc, not written in Zig.

There are way too many builtin symbols IMO. For example, all we need for List are

  • get
  • set
  • insert
  • remove
  • len

The rest can be written in Roc.

@iacore
Copy link
Contributor

iacore commented Nov 10, 2021

I think we should define clearly what should go in where of:

  1. Compiler built (in zig/rust)
  2. Standard library (in roc)
  3. Platform

Let's say I want to write commerce software that deal with currency. I want to make Float backed by DEC64 for no loss in precision in decimal. How do I swap out the implementation of Float and expect all other functions to work?

@rtfeldman
Copy link
Sponsor Contributor Author

rtfeldman commented Nov 10, 2021

Is it necessary to include Str, Dict and Set as builtin?

Str yes, because the small string optimization is important for Roc since we don't use tracing GC with a bump-allocated nursery. It's not possible to implement that optimization in pure Roc.

Even if that weren't the case, Str would still be an opaque type which differs from List U8 in that it should have validated UTF-8 bytes. String literals should compile to Str rather than List U8, and it should be possible to have a Str -> List U8 conversion function, but the other way around should require a Result for UTF-8 validation.

Dict and Set depend on how #1955 turns out!

Standard library (in roc)

The Roc standard library refers to the builtins. The reason I chose the term builtins is to emphasize the fact that in Roc, the implementation of the standard library is built into the compiler. 😄

(It needs to be so that we can add extra metadata that gets used behind the scenes in compiler performance optimizations. That metadata should not be exposed outside the compiler!)

There are way too many builtin symbols IMO.

The priority with builtin types is for them to have nice Roc APIs and to run as fast as possible under the hood. I'm fine with however many symbols that ends up requiring!

Let's say I want to write commerce software that deal with currency.

We have a builtin Dec type for that. It's only partially implemented if you're looking for something to work on!

See #1494 (comment) for the most recent developments.

@joshuawarner32
Copy link
Collaborator

For the map<N> implementations, is there any way we can have those magically auto-generated by the compiler? Seems pretty silly to not generalize that.

@JanCVanB
Copy link
Sponsor Collaborator

@matthiasbeyer Thanks for your comment. I've marked Num.divFloor as done, hopefully that's correct.
@rvcas Thanks for your PR! I've marked Num.toStr as done, hopefully that's correct.

@JanCVanB
Copy link
Sponsor Collaborator

Should the request for Num.fromStr be removed, in favor of using the more-specific and already-implemented Str.to* functions (Str.toI64, Str.toU8, Str.toNat, etc.)?

@rtfeldman
Copy link
Sponsor Contributor Author

In this case I think we'd rather have one Num.fromStr : Num * -> Str that works on any numeric type you give it.

Unlike some of the other scenarios we've talked about, I don't think there's anything particularly error-prone about the more flexible Num * design in this case, so might as well have one flexible function!

@JanCVanB
Copy link
Sponsor Collaborator

JanCVanB commented Jan 20, 2022

What would be the type of Num.fromStr -1, if it must be signed? Would the compiler error on Num.fromStr -1 |> functionThatRequiresAU8?

Should the annotation instead be Num.fromStr : Num * -> Result (Num *) [ InvalidNumStr ]*, to match the Err cases of Str.toI8 and its friends (for situations like Num.fromStr "-200_000_000_000_000_000_000_000_000_000_000_000_000" that don't fit in any number type)?

(Should I move this Num.fromStr discussion to its own issue? 😛)

@rtfeldman
Copy link
Sponsor Contributor Author

Sorry, my mistake - for some reason I was thinking of Num.toStr : Num * -> Str and not fromStr (Num * -> Str would be a very strange type for a fromStr function!)

My excuse is that it's past midnight here. 😆

Anyway, I think you're right - we should open a separate issue for this, and also that we should probably have individual functions - one for each numeric type - to convert a string to that numeric type.

@JanCVanB
Copy link
Sponsor Collaborator

JanCVanB commented Jan 27, 2022

@rtfeldman Mind if I delete all completed tasks in the top comment? I don't know GH best practices for long task lists, but since more than half of the tasks are completed, it seems helpful to trim it down for clarity. (Perhaps I'd leave one completed task like List.update to exemplify ideal formatting of a completed task.)

@rtfeldman
Copy link
Sponsor Contributor Author

@JanCVanB Yeah, go for it! 👍

@JanCVanB
Copy link
Sponsor Collaborator

JanCVanB commented Jan 28, 2022

40+ down, 40+ to go! Thank you, everyone who implemented this first batch of new builtins 😃

Num

  • toStr : Num * -> Str
  • divFloor : Int a, Int a -> Int a
  • divCeil : Int a, Int a -> Int a
  • minI128 : I128

List

Result

  • default : Result ok *, ok -> ok
  • map : Result before err, (before -> after) -> Result after err
  • mapErr : Result ok before, (before -> after) -> Result ok after

Str

And @rvcas, thank you for the unlisted Str.to{Num *} builtins!

@ayazhafiz ayazhafiz added the P-high High priority/frequency label Feb 15, 2022
@ayazhafiz
Copy link
Sponsor Member

Marking this as high prio given the increasing number of folks interested in using Roc joining.

@snprajwal
Copy link
Contributor

@rtfeldman It would be great if this list could be updated, since a lot of them have been implemented since June

@ayazhafiz
Copy link
Sponsor Member

@snprajwal updated!

@Lunarmagpie
Copy link
Contributor

walkFrom and walkFromUntil are already implemented. They should be checked off the list.

@JanCVanB
Copy link
Sponsor Collaborator

@Lunarmagpie updated!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P-high High priority/frequency
Projects
None yet
Development

No branches or pull requests

10 participants