Live data from Hacker News

Microfeatures I'd like to see in more languages

buttondown.email

341–350 of 539 posts

Re: Microfeatures I'd like to see in more languages

#341
post #206

Earlier quoted context omitted.

As a choice then perhaps but as a default and unalterable behaviour it can be a bloody timewaster when negative subscripts are a runtime error in your work. I've hit that in python and didn't enjoy it.

A nice alternative I've seen is that negative index is an error, but there is special syntax for indexing from the back like array[end], array[end-1], array[end-n], where n is a (positive) variable. Likewise, end can be used in range definitions like array[5:end]. Julia and Matlab both have this.

C# has a very nice approach to this: indices aren't simple numbers, but values of type Index [1], which store both the offset and the direction, and can be implicitly created for plain ints. When you do want to index from the end, you use the unary ^ operator to create a reverse index. Thus, you can write things like a[^1] or a[0..^1].

But, more importantly, it means that any custom collection type can define an indexer that can handle reverse indices in the manner that is appropriate for that particular collection; it's not just for arrays.

[1] https://learn.microsoft.com/en-us/dotnet/api/system.index

Re: Microfeatures I'd like to see in more languages

#342
post #307

Comments Section In Next Generation Shell I've experimented by adding section "arbitrary comment" { code here } and this is staying in the language. It looks good. That's instead of # blah section - start code here # blah section - end Later, since NGS knows about sections, I can potentially add section info to stack traces (also maybe logging and debugging messages). At the moment, it's just an aesthetic comments an…

If it's just for comments, IIRC Lisp has docstrings - the very first expression in a Lisp function can be a string literal which gets compiled into the final executable as a docstring which can be retrieved at runtime.

Re: Microfeatures I'd like to see in more languages

#343
post #4

My favorite is uniform function call syntax. In several languages (Nim, Koka, D, …), you can always write bar.foo(baz) instead of foo(bar, baz) and vice-versa. Another one from Nim is the implicit result variable. Instead of having to do this: func sum(nums: seq[int]): int = var result = 0 for num in nums: result += num return result you just do this: func sum(nums: seq[int]): int = for num in nums: result += num It…

> My favorite is uniform function call syntax. In several languages (Nim, Koka, D, …), you can always write bar.foo(baz) instead of foo(bar, baz) and vice-versa. To me, these are "Tell bar's foo to do something with baz." and "Tell foo to do something with bar and baz.". So being 'able' to flipflop the syntax is at least temporarily semantic'ly confusing.

That arguably depends on your POV. Thinking like python where a method always declares 'self' as the first argument, then a function is just 1 thing (there's no such thing as a method). Then dot syntax is just syntactic sugar for passing the first argument, and there's nothing special about functions. You can manually pass the first argument.

In other words, to me it's simpler and therefore less confusing.

Re: Microfeatures I'd like to see in more languages

#344

For rust, it is probably the try (?) operator. Fundamentally, it's just syntax sugar for a match statement with an early return in the Error or None cases, but it really improves the ergonomics of dealing with Result and Option types.

Interestingly, there was once a solid effort to add a try operator to Go. While the proposal was quite well received, upon closer inspection it was realized it would be essentially useless in the real world as, given how the rest of the language works, you almost never would want to simply early return with the value received. The data revealed that the vast majority of the code in the wild that the syntax sugar woul…

In Rust, when you use `?`, it includes a step to convert the error type of the expression it was used on into the (possibly different) error type that the current function returns. So if you need to map low-level errors to high-level ones in a consistent way, you'd just do it once when defining that error type.

Re: Microfeatures I'd like to see in more languages

#345
post #58

Lua also allows you to choose the string delimiter. If your string contains "]]" you can delimit it with [=[ or [==[ instead. Any number of "=" so long as the opening and closing delimiters match.

And that's why all modern languages implement streams/string helpers/string builders. You do not want to actually write strings/manipulate them using "+" (concatenation symbol) in code directly because, in modern Unicode world, it tends to become a point of failure for obscure bugs / a maintenance horror show.

String builders originated in languages with immutable strings making code using something like "foo += bar" in a loop very expensive due to the need to allocate a new string on every iteration. A string builder is basically a mutable string that can be built in-place efficiently and converted to a proper immutable string at the end. It is purely a performance thing, and there are no Unicode issues when concatenating valid Unicode strings (i.e. sequences of codepoints).

Re: Microfeatures I'd like to see in more languages

#346

Elixir's sigils are amazing. There are date sigils that allow you to do what the OP does: ~N[2023-01-01 12:00:00] But you can also define your own sigils to create new "custom syntax" for almost any struct. Kind of a special case of reader macros, I guess. Very convenient.

Swift has the expressibleby Type literal series of protocols for this. For example you could write an extension on Date to add initialization from a string: extension Date: ExpressibleByStringLiteral { public init(stringLiteral value: String) { // parse the string here. } } You can then do things like: let happyNewYear: Date = “2023-01-01 12:00:00” There are a protocols for all literal types. For example, you could i…

C++ has the same with implicit constructors, generally considered to be a footgun that should be disabled with the explicit-keyword unless such a cast makes sense, implicit constructors are otherwise the default. For example vector has a constructor with takes integer size argument, if it wasn't explicit you could accidentally do vector v = {10} which would construct a vector with 10 empty elements, instead of one element with value 10. This also has to do with the ambigous curly brace syntax in c++.

Re: Microfeatures I'd like to see in more languages

#347

About kebab-case identifiers. What I always wanted is proper spaces! Designing syntax where identifier could have spaces (without backticks or something like that) might be tricky of course. But may be it's not impossible. All those space imitations, whether they're dashes, underscores or camels - they're just imitations. Nothing compares to real spaces. If anything, underscores are closest ones, if you ask me.

It's pretty easy, actually, and was common in early PL designs such as ALGOL. All you need to do is make a special syntax for keywords - https://en.wikipedia.org/wiki/Stropping_(syntax) - and then whitespace becomes completely redundant for tokenization purposes, and can be ignored altogether, or treated as part of the identifier in which it occurs.

Re: Microfeatures I'd like to see in more languages

#348

Keyword and optional arguments (seen in e.g. Python, Bash with --flags, and OCaml) are my favorite language superpower. They make code more self-documenting and let you add add optional behaviors to functions. This makes it really easy to make concise, highly usable APIs.

In OCaml, they are a bit more subtle:

   let x = ... in
   some_function ~x
if the parameter has the same name on both sides (caller, callee) there's a syntactic shortcut. It's a small but noticeable force that pushes you towards more consistent naming.

Re: Microfeatures I'd like to see in more languages

#349

Earlier quoted context omitted.

I was under the impression that Elixir introduced this.

Elixir has forward pipes, but didn't invent them. For instance Racket and Clojure have threading macros , which are more flexible as they're just macros (Clojure's `->` is equivalent to Elixir's pipe operator, but `->>` will fill in the last parameter rather than first, and `-->` lets you use a keyword to define where the parameter is inserted in each call). Haskell let anyone who wants define their own pipe operator…

The earliest I've seen |> specifically in stdlib was in F#, which still predates Elixir by several years.

Re: Microfeatures I'd like to see in more languages

#350

Strongly-typed units and unit literals (e.g. 3mL, 10gal, 15m / 3s = 5m/s) AFAIK F# has these and that's about it

I see this in some Rust crates, as you can implement traits for built-in, primitive types.

For instance, the `embedded_time` crate lets you do

    200.microseconds()
    5.Hz()
https://docs.rs/embedded-time/latest/embedded_time/
Post reply on HN