Unidiomatic Zig exercises

About a third of the Haskell exercises use Either or Maybe. About two-fifths of the Zig exercises use Error. Slightly more than half the Roc exercises use Result.

Without learning Roc, my impression is that changing a Zig exercise to use try and ! is equivalent to changing a Roc exercise to use Result.

2 Likes

Reply is not directly in response to you @mk-mxp just where the topic is coming to light, I think. I agree with you.

I believe that in general Exercism teaches “library building” not “application building” which means that the library should return exceptions wherever exceptions should land, while allowing the client of that library to handle exceptions as it seems fit.

So returns that are expected are generally happy path, except for expected handling of some expected “exceptional” behaviors.

The exercise, in general, should test to the minimal bar of what it means to have achieved the exercise, leaving the student (in Practice exercises, not so much in concept exercises) open to explore whatever else they would want to explore, in terms of approaches, and including validations.

2 Likes

How do you feel about the general message posed by OP?

Is this something you think would benefit our students?

1 Like

I only used it as a command recently and I totally forgot that a copy of Zen is in Language Reference. My bad.

Yes, this! Thank you!

This is totally untrue. It is some of the tests currently provided by Exercism do not allow an option to return an error value on invalid inputs. I described a way to create such an option:

Yes, it is “agnostic”.

Most of these are OutOfMemory. They are not directly related to input validation. Good thing is that students have an option to add errors to error sets in these exercises.

I don’t think we need to add try to every exercise, or add a error-handling note to every message.

Exercise Summary
acronym all input valid
affine-cipher AffineCipherError
allergies all input valid
all-your-base ConversionError
anagram allows errors
armstrong-numbers all input valid
atbash-cipher students can choose to assert valid UTF-8
binary-search all input valid
bob students can choose to assert valid UTF-8
book-store Student can assert each book is valid (1…5)
bottle-song Use std.debug.assert or return an error.
change ChangeError, students can also assert coins are distinct and non-zero.
collatz-conjecture ComputationError.IllegalArgument
crypto-square allows errors. Students can choose to assert valid UTF-8
darts students can assert coordinates are not NaN
diamond stub asserts letter is valid
difference-of-squares In the event of overflow, can panic, wraparound or saturate
dnd-character students can assert modifier() input is 3…18.
dominoes students might assert stones contain 1…6 only, but this contraint is not stated in instructions.
eliuds-eggs all input valid
etl allows errors. Students can also assert letters are valid and never repeated.
food-chain PR #504
grains ChessboardError, might be removed in issue #229
hamming DnaError
hello-world no input
high-scores optional (to allow for empty scores list)
house PR #504
isbn-verifier return false for disallowed characters
isogram instructions don’t specify what happens if characters other than letters, spaces or hyphens repeat
killer-sudoku-helper students can assert buffer length is sufficient
kindergarten-garden students can assert input is valid
knapsack allows errors
largest-series-product SeriesError
leap Without outside knowledge (adoption of Gregorian calendar), any input is valid
linked-list pop() and shift() can return null. No requirement for push() or unshift() to detect if node is already in a list
luhn return false for disallowed characters
matching-brackets Any other characters should be ignored.
matrix allows errors
meetup year asserts would be country-specific
micro-blog students can choose to assert valid UTF-8
nth-prime students can assert number is not 0
nucleotide-count NucleotideError
ocr-numbers RecognitionError
palindrome-products students can assert min <= max
pangram students can choose to assert valid UTF-8
pascals-triangle all input valid
perfect-numbers Asserts that n is nonzero.
phone-number optional
piecing-it-together PuzzleError
pig-latin students can choose to assert valid UTF-8
prime-factors students can assert number is not 0
proverb all input valid
pythagorean-triplet all input valid
queen-attack QueenError, might be removed in issue #223
rail-fence-cipher We should add “You may assume there are at least two rails”. Then students can assert.
raindrops all input valid
rectangles Any unexpected characters may be ignored. Non-rectangular input not possible.
resistor-color all input valid
resistor-color-duo all input valid
resistor-color-trio all input valid
reverse-string students can assert buffer length is sufficient
rna-transcription students can use assert, or define an error
robot-simulator Any instructions other than R, L and A may be ignored.
roman-numerals students can assert number is in supported range
rotational-cipher students can choose to assert valid UTF-8
run-length-encoding For simplicity, students can assert input strings are valid and buffer size is sufficient
say SayError
scrabble-score students can choose to assert valid UTF-8 and that letters are all roman
secret-handshake all input valid
sieve students can assert buffer size is sufficient. We should change type of limit, perhaps to u12
space-age all input valid
spiral-matrix all input valid
square-root students can use assert, or can approximate
state-of-tic-tac-toe GameState.impossible
sublist all input valid
sum-of-multiples allows errors
triangle TriangleError (defined by student)
twelve-days PR #504
two-bucket optional
two-fer allows errors
variable-length-quantity DecodeError
word-count allows errors
wordy ArgumentError
yacht students can assert all dice are 1…6
5 Likes

Good place to allow returning errors.

Year 0 is a huge undefined behavior.

Buffer length could be too short.

I understand your three reactions. We are very keen on not adding complexity where the input data doesn’t require it (across all tracks). So whilst these things are possible, they are not requirements of the exercise and adding them would make the exercises harder.

Instead, if you want to play with this, wouldn’t something like this work?

// expose the version without errors for exercism
pub fn the_function(...) ... {
    your_version(...) catch |err| {
      @panic(std.fmt.allocPrint(...) catch unreachable);
    };
}

// add error handling and whatever you want to have fun
fn  your_version(...) {

}

Test runner stops after the first panic but it proceeds with tests even if some test returns an error. This should hint that panic and error are fundamentally different. You can not replace an error value with a panic.

Panic stands for unrecoverable violation of an invariant. Something wrong with the program. It is a bug.

Error stands for some unfavorable condition in the environment. Missing file, lost network connection, corrupted input data, denied permission. Nothing is wrong with the program. It is not a bug.

Sure, I can build a workaround. But then I do not need Exercism for it. Why bother messing with Exercism if I need to do everything myself anyway? But then why Zig official site refers to Exercism as a lerning resource:

Zig on Exercism Solve coding exercises and get mentored to develop fluency in Zig.

Fluency in Zig must include fluency in error values, error sets and error unions. The is no way around it. Zig Is not C where you can ignore errors. Zig is not Python where exceptions hide the control flow. Zig is very explicit about errors.

You suggest to skip errors from exercises in the name of not adding complexity. But then you suggest to add a disfunctional complexity just to use a basic concept in the language I am trying to learn.

I do not think we always need to add requirements. I think allowing students to have more options is enough. Instructions and tests cases can still be the same. Exercises do not need to be harder. All current solutions should still work.

Bottle song exercise updated recently. Instructions read:

Detect invalid input

This really puzzled me. Because my old solution passed all the tests after I added ! to the return type. I was so used to ignoring invalid inputs after solving dozens of exercises that I totally missed three different ways the inputs could be invalid.

I am happy with the updated version. Now I can explicitly return an error value without the complexity of a workoround.

If you’re trying to make a point, you should perhaps not use these types of hyperboles when someone is making a suggestion. The forcefulness with how you’re convinced that this change is barely any change at all and how you dismiss others’ their feedback that Zig isn’t a language where one should always validate input don’t make me interested in further engaging.

Good luck with convincing the maintainers of this track. I will now withdraw my support and leave it to the others.

It is not a hyperbole. It is literally disfunctional. Panic does not function the way error value functions. You can not run the rest of the tests if the first test panics. I am not trying to force anything on anyone. Inferred error set does not force you to validate input.

You’re never going to reach the panic because there is no input to get to the panic. So good luck with that.

Because I love logic and calling out fallacies, I name thee the Nirvana fallacy aka “Don’t let perfect be the enemy of the good”.

One can develop fluency in a language bit by bit. One can practice fluency in certain areas while not practicing fluency in others. That’s how we can have some exercises that deal with numbers, others with strings and others with graphs without needing everything to all be in one exercise :slight_smile: The fact that error handling isn’t a partof an exercise doesn’t mean you can’t develop Zig fluency by working on that exercise.

2 Likes

What about that code is disfunctional? Is there a syntax error? It looks like it ought to function perfectly well.

The above suggest shifts the complexity from where it impacts all users to where you can opt to practice the concept you indicate interest in learning. This way (1) it doesn’t impact other students and (2) you get to learn and practice the thing you indicated interest in learning. Does that accomplish your goal?

1 Like

Thank you for reminding me about fallacies. I am not that educated in that field so I am always curious to learn a new one.

True.

Mostly true. It defeats the purpose of using Exercism to simplify learning the language though. It is simpler to learn Zig without Exercism than to learn it with Exercism and the workaround.

Not exactly true. Other users will not suffer from added complexity. Existing solutions only need to add ! to return type. New solutions will have ! from the stub. Instructions do not need to change. Nobody is forced to validate inputs. There is not that much complexity to shift.

The complexity of having an inferred error set is similar to the complexity of Python implicitly allowing to raise any exception anywhere. The student can simply ignore it if they are not ready to learn about errors.

The Exercism tracks aim to provide a place where you can practice many aspects of a language. Rarely does Exercism cover every aspect. The tracks are built by volunteers and covering every aspect of a language is hard.

The work around would be pretty simple – copy/paste the structure provided above. Unless I’m missing something, that doesn’t add a ton of work. If that additional work makes Exercism not worth using to practice error handling, then you can opt to practice error handling elsewhere, or possibly help write specific error handling exercises. Or maybe the track maintainers will change some of the exercises to involve more error handling.

Hopefully error handling isn’t the only part of Zig you are interested in practicing, though, and the track provides you with an amazing resource to gain fluency in many other aspects of the language!

That would be a sad outcome.

Exercism isn’t set up in a way where it’s practical for every track to explore every aspect of that language. The tracks are built by volunteers. We leverage a common language-agnostic set of problem specs that allow us to build out practice exercises fairly quickly – but those exercises are based on language agnostic data that do not attempt to explore the nuances of each language.

Some tracks have a syllabus with concept docs and exercises which do explore language specific concepts, but those tend to be fairly expensive and time consuming to build it. If you’d like to see a specific track explore specific concepts, you can help make it happen! We’re always looking for volunteers to help build out track syllabi.

If you’re looking for a platform that covers a language comprehensively, Exercism is very far from that. We may get there slowly as people help build out track syllabi, but that’s not what Exercism currently offers.

Exercism does offer a large number of tracks which have a large number of exercises. Those exercises are great for practicing and developing fluency across many aspects of over 70 languages. If that is helpful to you, we have that. If that’s only helpful if the exercises cover every aspect of a language, Exercism may not be the best fit for you.

1 Like