Elixir’s testing library uses meta programming to show the code that fails and what the values were at both sides of a comparison. IE a = 1; b = 2 assert a == b Will fail with error like: Assertion failed, a == b Left is 1 Right is 2 So you don’t have a bunch of assert-functions; you just assert anything and it will spit out a decent error.
Microfeatures I'd like to see in more languages
501–510 of 539 posts
Re: Microfeatures I'd like to see in more languages
#502Earlier quoted context omitted.
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.
Which too requires the language to have a 'the producer is always right' over a 'the customer is always right' design, which Rust does. It all works well when the language is designed for it, but it has to be there at the macro level. Definitely not a 'microfeature'.
What do you mean by those two quoted terms?
Re: Microfeatures I'd like to see in more languages
#503Earlier quoted context omitted.
Is there a link to this discussion? This seems interesting. If I can’t make a call to a downstream service, or a file I’m trying to read doesn’t exist, or a s3 bucket 404’s, or almost any other “real world” error I can think of, the only (sane) way I can think of handling this is propagating the error down to the caller (and perhaps logging?) Do you mean to say that it is idiomatic in Go to handle errors by… doing so…
> the only (sane) way I can think of handling this is propagating the error down to the caller A big problem, among many, with doing that is that you leak implementation details out of the abstraction. If, to stick with your example, you have a function that helps you with reading files, the caller shouldn't care where the data is stored. Today it might be the local filesystem, tomorrow S3, and when you make that cha…
This would lead to the situation where a local call is treated as the same thing to a network call. Which is know to be a very bad design.
> Like the sibling comment points out, Rust does "from" conversion when using try (?) to try and avoid encountering the same fate.
Yeah, and it avoids all the hassle.
Why couldn't any language (and especially Go) just do the same?
Re: Microfeatures I'd like to see in more languages
#504Agree with kebab-case. > Most languages have multiline literals, but what makes the Lua version great is that the beginning and ending marks are different characters. This solves the infuriating “unnestable quotes” problem string literals have, and you don’t have to escape all your literal \s. That paragraph also uses “nestable marks”.
Nestable comment syntax is also nice. At least some MLs (eg SML) has it, that I know of. Indentation-sensitivity can also solve similar problems. (Indentation does not have to exclude requiring graphic termination. A formal language can require both. Or just a helpful tool.) (Also agree with 'kebab-case', although the name is new to me and a bit weird.)
Scala has it too. (But OK, Scala is a kind of ML).
Re: Microfeatures I'd like to see in more languages
#505# Function Shorthand #### I like how functions in js can be `arg => result`. In F# I have to do `fun arg -> result` with the `fun` keyword. It makes sense since `MyArgType -> MyResType` is a type signature in f#, but I feel like the compiler can just check if the arguments are references to types or are argument bindings. # Multiline Lists/Arrays #### I like how F# doesn't require delimiters for multiline lists. So I…
> I feel like the compiler can just check if the arguments are references to types or are argument bindings. 1. this is absolutely terrible because now you need feedback from the type checker to know how to parse the program 2. it is furthermore also ambiguous with function application , requiring arbitrary lookahead to disambiguate, also not a fun thing to do JS gets away with it because the sigil was not previously…
val f: Any => String =
any => any.toStringRe: Microfeatures I'd like to see in more languages
#506Earlier quoted context omitted.
> the only (sane) way I can think of handling this is propagating the error down to the caller A big problem, among many, with doing that is that you leak implementation details out of the abstraction. If, to stick with your example, you have a function that helps you with reading files, the caller shouldn't care where the data is stored. Today it might be the local filesystem, tomorrow S3, and when you make that cha…
> A big problem, among many, with doing that is that you leak implementation details out of the abstraction. If, to stick with your example, you have a function that helps you with reading files, the caller shouldn't care where the data is stored. Today it might be the local filesystem, tomorrow S3, and when you make that change nothing about the rest of the program should break. This would lead to the situation wher…
If your abstraction leaks that the implementation is a local call, and then you try and change that later, unquestionably. Again, you need to avoid leaking implementation details, which is too why you can't just add a try operator and make it automatically useful. Any leak of any kind in your abstraction will make life miserable later. Don't let your abstraction leak.
> Yeah, and it avoids all the hassle.
All it does is move where the code is located, placing the onus on the producer "the producer is always right" instead of the caller "the customer is always right". You don't actually avoid anything, just change the perspective.
> Why couldn't any language (and especially Go) just do the same?
Perhaps it could, but it requires that the language take a more macro look at the problem. It is not a microfeature.
Re: Microfeatures I'd like to see in more languages
#507# Function Shorthand #### I like how functions in js can be `arg => result`. In F# I have to do `fun arg -> result` with the `fun` keyword. It makes sense since `MyArgType -> MyResType` is a type signature in f#, but I feel like the compiler can just check if the arguments are references to types or are argument bindings. # Multiline Lists/Arrays #### I like how F# doesn't require delimiters for multiline lists. So I…
List("a", "b").map(_.toUpperCase).mkString(",")
It's the shorthand for: List("a", "b").map(elem => elem.toUpperCase).mkString(",")
(Which shows the firstly proposed feature :-))Re: Microfeatures I'd like to see in more languages
#508Strongly-typed units and unit literals (e.g. 3mL, 10gal, 15m / 3s = 5m/s) AFAIK F# has these and that's about it
Re: Microfeatures I'd like to see in more languages
#509I might add kebab-case to my current language project. From all the code I've written, I only found a handful of - operators not surrounded by spaces, so that ambiguity wouldn't bite me often. Also, I wish the unary negation operator was more visually salient. `foo * -bar` is very different from `foo * bar`, but it's only a handful of pixels on the screen. I've thought about trying to render it as an em-dash or somet…
Kebab-case and snake_case may seem to read better when looked at code like it would be written text, but they read worse than camelCase when looked at it in a symbolic way.
Re: Microfeatures I'd like to see in more languages
#510WebGL's swizzling vector selectors.[1] Where v.x desugars as v[0], v.y as v[1]. Similarly for z and w. Also r,g,b,a. And they swizzle: v.rgb, v.xz, v.zx . So `v1.xy = v0.yx` reflects. [1] https://www.w3.org/TR/WGSL/#vector-access-expr
Therefore I would prefer something like this to be the usual array access syntax:
val chars = Array("a", "b", "c")
val secondChar = a.2 // as a shorthand for `chars.atIndex(2)`, or equivalently `chars.atOffset(1)`, maybe also with `a..1` for the offset case
(Also we should stop calling the offset "index", and get a proper "atIndex" method.)