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

Non-ideal discoverability of Janet divergences from other programming languages #197

Open
fnaj77 opened this issue Jul 14, 2023 · 9 comments

Comments

@fnaj77
Copy link

fnaj77 commented Jul 14, 2023

Hi to all,
this is more of a suggestion than a problem per se.

As a newcomer, I accidentally discovered some peculiar features of the Janet language that set it apart from other programming languages. I'm quite sure they are rock-solid choices made by experienced people, and I'm not going to criticize them or propose changes.

But I think it could be beneficial, at least for beginners like me, to have a section of the Janet documentation devoted to highlighting conventions in Janet that might be different from what one might expect from other, widely used, programming languages.

Just to give some examples, I'm thinking about -2 used to refer to the last item in an array/tuple[1] or the 0-based index for day and month only in os/date[2], and I don't know how many other cases of this kind may exist.

I know that all these behaviors are well and clearly specified in the relevant docstrings but, as I said, I think it could be beneficial for beginners to have them listed on a single page and not scattered all around the documentation.

To be more clear, I'm not advocating changes in language semantic and/or behavior, just more "prime time" in the documentation about these divergences from common practice. I'm thinking about something in the line of "Janet for pythonists/clojurists" or "Janet for C/C++ developer" etc.

Please, above all, take this as a constructive proposal, I do not want to criticize someone else's free time/contribution.
Thank you.

[1] janet-lang/janet#1219 (comment)
[2] janet-lang/janet#1214 (comment)

@tionis
Copy link
Contributor

tionis commented Jul 14, 2023

The behaviour of the match operator for shorter tuples would also be relevant here.
This is explained in janet.guide/control-flow at “This is terrible, and you will mess this up at some point”

@fnaj77
Copy link
Author

fnaj77 commented Jul 14, 2023

The behaviour of the match operator for shorter tuples would also be relevant here. This is explained in janet.guide/control-flow at “This is terrible, and you will mess this up at some point”

Hi @tionis,
you're right, match macro is ... funny to use too :)

@sogaiu
Copy link
Contributor

sogaiu commented Jul 17, 2023

I think it would be convenient for users to be able to discover divergences (to adopt the terminology of the issue's title) and/or potential gotchas.

I'm not really sure how to do this well though.

A single list might be nice, though for some things, perhaps one would want to learn about individual items in context (e.g. there is an example of slicing with a negative index in an example of this section). I suppose there could be a list which is pointed at from specific sections (or a specific part of the list could be linked to).

Note though that for negative index use, this might lead to a fair bit of extra text spread across multiple sections. That might not be so great from a maintenance perspective if certain changes were to be made later.

I hope it's clear from the little examination above that it's not necessarily a no-brainer to do this kind of thing in a maintainable manner. That's not to say that things couldn't be improved, just that there may not be a single easy-to-execute approach. Still, perhaps a good idea will come about or individual items might be improved upon.

For the moment, may be this issue could collect some potential content -- though if it's distributed throughout the issue, it may become unwieldy to act upon items from a practical perspective....

@uvtc
Copy link
Contributor

uvtc commented Jul 18, 2023

Ok, time to pop my head out for a moment! :) I've seen two of these elsewhere, and thought they were pretty useful (full disclosure, years ago I wrote a few of the ones for Ruby (though I expect they've been updated a bit since then)) :

The ones for Julia are more lumped together -- I think the ones for Ruby are more nicely organized. :)

@sogaiu
Copy link
Contributor

sogaiu commented Jul 18, 2023

@uvtc Thanks for sharing those, will be working on digesting them.


P.S. Good to hear from you -- been missing your presence!

@uvtc
Copy link
Contributor

uvtc commented Jul 18, 2023

Aw, thanks, sogaiu!

@sogaiu
Copy link
Contributor

sogaiu commented Jul 19, 2023

Along the lines of improving the existing documentation for the case of providing some explanation of how negative indices work in Janet, I think this section is a candidate for an addition.

@sogaiu
Copy link
Contributor

sogaiu commented Jul 22, 2023

Looking at the Ruby and Julia resources I was reminded of this.

@sogaiu
Copy link
Contributor

sogaiu commented Dec 22, 2023

I'm not sure yet whether the following should count, but I'll note it for future reference...

The */slice functions all have an optional start argument. The docstring for string/slice is currently:

    (string/slice bytes &opt start end)

    Returns a substring from a byte sequence. The substring is from 
    index `start` inclusive to index `end`, exclusive. All indexing is 
    from 0. `start` and `end` can also be negative to indicate indexing 
    from the end of the string. Note that if `start` is negative it is 
    exclusive, and if `end` is negative it is inclusive, to allow a 
    full negative slice range.

For the non-negative value cases, start can range from 0 through the length (NOT limited to 1 less than the length -- this is not mentioned in the docstring) of the argument being sliced.

For example, if slicing something of length 1, start can be 0 or as shown below, 1:

$ janet
Janet 1.32.1-11d7af3f linux/x64/gcc - '(doc)' for help
repl:1:> (string/slice "a" 1)
""
repl:2:> (array/slice @["a"] 1)
@[]
repl:3:> (buffer/slice @"a" 1)
@""
repl:4:> (keyword/slice :a 1)
:
repl:5:> (tuple/slice ["a"] 1)
()
repl:6:> (type (symbol/slice 'a 1))
:symbol
repl:7:> (length (symbol/slice 'a 1))
0

This was unexpected to me [1], but thinking of the value of start as representing or pointing to a space or gap between elements made it less odd, e.g. for a string:

byte position:  0 1 2 3 4 5 6 7 8
----------------------------------
       string:  ( d e f   a   1 )
      indeces: 0 1 2 3 4 5 6 7 8 9

In the case of a string of length 1, that might look like:

byte position:  0
------------------
       string:  x
      indeces: 0 1

I'll note that this may not be a divergence from other programming languages, possibly it might be considered a gotcha (but may be not).


[1] On a side note, it looks like one may produce a symbol of length 0:

repl:6:> (type (symbol/slice 'a 1))
:symbol
repl:7:> (length (symbol/slice 'a 1))
0

That seems a bit odd to me. Not sure if that's problematic...

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

4 participants