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

print functions signature update proposal #1082

Open
konradekk opened this issue Aug 15, 2022 · 4 comments
Open

print functions signature update proposal #1082

konradekk opened this issue Aug 15, 2022 · 4 comments

Comments

@konradekk
Copy link

konradekk commented Aug 15, 2022

Got recently dragged into the whole effort of SerenityOS and, in the effect, this of Jakt language. Most certainly by the personal traits of Andreas and Jonathan. Putting all the accolades and awes aside I thought I’ll share some ”outsider” perspective on the language itself (as I think is pretty interesting as having a clear purpose that will drive its development—something that some other languages tend lack).

What I’ve noticed is this ”named” parameters approach for method calls which I really like. Having seen also ES/TS interpolation strings I found them very useful and straightforward so I was pretty shocked they did not land in the language (yet?). Adding two plus two, I thought that would be nice to marry those ideas. After a moment of thought I came to realisation that having something similar to ES/TS approach (probably well-to-known to the creators) might be not the best thing in the end. I thought that I might want to bite too much at once.

I’ve limited my thinking process to the places I use this interpolation pattern most. And this was just printing/logging. Trying to see things from this perspective I’ve noticed that print functions use anonymous parameters and {} placeholders. ES/TS interpolation has inline formatting but has pretty much the same drawback as the current approach in Jakt—you have to extract you expression into a variable if you want to re-use it.

By simply using named parameters in print function (and maybe other formatting functions I’m not aware at the moment) that would be parsed in the formatting string, one could avoid artificiality and go for explicitness that Jakt is aiming for. I do not have exact syntax for that and not really thinking about any at the moment as there are many examples in the wild and most probably community has already it’s own preferences. I’ll try to produce an example though:

println(
    "Copying file {blue}{firstFile}{reset} to file {blue}{secondFile}{reset}",
    firstFile, secondFile,
    blue: "\u001b[34m", reset: "\u001b[0m"
)

This is all about the thing I wanted to share with you passing on the whole string interpolation topic for now. 😋

@alimpfard
Copy link
Member

alimpfard commented Aug 15, 2022

Objectively speaking, this has three requirements to implement:

  • named variadic generics (we do not yet have an actual implementation of variadic generics)
  • preserving the names in a runtime structure (reflection can help this)
  • implementation of the format stuff

We cannot easily pull our current trick or specialising in the typechecker to compensate for the missing variadic fn support, however.

Personally though, I feel like this is a bit too complex 🤔

@konradekk
Copy link
Author

konradekk commented Aug 15, 2022

Thanks for prompt reply! I feel somewhat flattered that we’re talking about implementation or even do an opportunity analysis! 😳

Just after posting I thought that I haven’t seen any named variadic parameters (but I just could miss them or they could be pretty new and their use could not be really spread out). I was just about proposing that implementing this idea could start slowly, i.e. without that and one could just pass an object there to side step the complexity. But I think that’s an implementation process so the decision is not up to me to make. So, modifying my previous example, something along those lines:

println(
    "Copying file {blue}{firstFile}{reset} to file {blue}{secondFile}{reset}", [
    firstFile, secondFile,
    blue: "\u001b[34m", reset: "\u001b[0m"
])

For now, if that’s the custom here, maybe we could start plainly with plain ”if” or ”whether” as this whole idea might be just not in line with the vision of language creators! 😅 For me: anything will do, esp. that I’m still an outsider! 😉 (What I really mean: don’t be afraid to play on the idea or even own it if needed! I wanted more to point to a possible readability shortcoming than propose anything specific here… which I apparently failed! 😂)

(I think I won’t jump into C++ programming, at least in a foreseeable future, but I think I could do some stuff in Jakt later on—splendid idea for selecting less error-prone language! Not really important if home-made or found on a shelf!)

@alimpfard
Copy link
Member

alimpfard commented Aug 16, 2022

Hmm...so we definitely want variadic generics (I've had a few attempts at implementing them, but mostly got distracted or didn't like the outcome), and named parameters are an integral part of the language now, so it makes sense to me to support named variadics.
My intuition says that we should keep things like this in userspace and limit the prelude impact as small as possible (as I mentioned, currently format-style functions are specially handled because we don't have variadic functions).

By giving users the means to implement this in the language, we can also sidestep the "what's the C++ implementation going to be like?" question, as well as limiting the "special" bits in the language.

For your revised example: we don't have anonymous structs (or named tuples if you want to call it that) either, so the complexity remains the same to me (was this inspired by Zig's std.debug.print by any chance?)

Anyhow, you're welcome to make a prototype, just something that'd let people play around with the idea and get a feel for it - at this stage we're very open to changes I'd say.


for instance, given support for the two primitives, this is what I imagine it'd look like:

function println<Args...>(format: String, anon args: Args...) {
    guard reflect Args is ArgumentPack(fields) else { panic() }
    mut lexer = SomeKindaLexer(format)
    for token in lexer {
        match token {
            Text(x) => print(x)
            Substitution(name) => print("{}", args[fields[name].index]) // type magic tho
        }
    }
}

(can't really resolve the runtime index on a heterogeneous argument pack, probably needs a nice manual vtable)

@konradekk
Copy link
Author

For your revised example: we don't have anonymous structs (or named tuples if you want to call it that) either, so the complexity remains the same to me (was this inspired by Zig's std.debug.print by any chance?)
Got it (as for Zig: nope; but also tracking the progress there… 😉 It could be from there, in fact, also Go or other languages—but here I just plainly used idea from aforementioned ES/TS).

Anyhow, you're welcome to make a prototype, just something that'd let people play around with the idea and get a feel for it - at this stage we're very open to changes I'd say.
Glad to hear that—still I need a stronger machine for dealing with all that stuff; that might happen in a month or so. That would mean that topic is open for anybody to take at this moment! 😆 (Thanks for words of encouragement!)

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

No branches or pull requests

2 participants