Skip to content

Language-specific exercises #352

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

Closed
ErikSchierboom opened this issue Aug 22, 2016 · 19 comments
Closed

Language-specific exercises #352

ErikSchierboom opened this issue Aug 22, 2016 · 19 comments

Comments

@ErikSchierboom
Copy link
Member

At the moment, there are a couple of exercises that are only relevant to one language. The best example is probably the lens-person exercise, which is only relevant to Haskell. Is having a language-specific exercise something that is considered good practice, or should we shy away from it? I ask this because F# has a very cool feature named computation expressions and I was wondering if I could make an exercise for that feature.

@Insti
Copy link
Contributor

Insti commented Aug 22, 2016

Go for it.
The more generic you can make the problem description the better.
And remember that you can always add a HINTS.md file in the language track that will add further language specific instructions to the Readme.

@ErikSchierboom
Copy link
Member Author

Okay cool!

@petertseng
Copy link
Member

petertseng commented Jan 17, 2017

As an aside (no action is required from this comment), the lens exercise is no longer Haskell-specific. Scala has a implementation too, which may be amusingly confusing because the metadata.yml still says "(Haskell-specific)", so seeing that in the list of Scala exercises may give a student pause.

Actually, maybe there is an action to be taken here... remove "Haskell specific" from lens-person. Maybe "Functional programming language specific"


I do want to ask whether an F#-specific exercise ever materialised, but I think I would have seen an x-common PR if it did, so I have to assume no.

I'm asking because the Rust track is now discussing some exercises that only make sense for it, since they extend an exercise (Luhn) with Rust-specific features (traits).

@NobbZ
Copy link
Member

NobbZ commented Jan 17, 2017

I'm asking because the Rust track is now discussing some exercises that only make sense for it, since they extend an exercise (Luhn) with Rust-specific features (traits).

I do not think that "traits" are specific to rust, but maybe named differently in other languages. As I do understand them, they are similar to Haskells classes, Elixirs protocols. Someone else told me, that rusts traits are even inspired by scalas traits.

@petertseng
Copy link
Member

petertseng commented Jan 17, 2017

I do not think that "traits" are specific to rust, but maybe named differently in other languages.

You have caught me exaggerating! I should not make such bold claims of uniqueness.

I guess the question that should be asked is - would other languages want to have the metadata for this new Luhn-based exercise in x-common? If yes, then maybe we will just add it to x-common! If no, then for now it is as if it were a language-specific exercise, if only the Rust track is interested in it.

Let's explain what the Rust proposals are, so that other languages can determine whether they are interested in them.

There are two proposals in the Rust track (exercism/rust#248), which both use Rust traits but, off the top of my head, admit the following possibilities in other languages:

  1. Make it so that there is an type called a Luhn. We can ask an object of this type whether it is valid. Using Rust traits, allow so that both strings and integers can be converted to this type.
    • Any language that supports explicitly defining how one type converts to another may use this. C++ has user-defined conversions.
    • In addition, I imagine typeclasses in Haskell would allow one to do much the same. instance Luhn Int where..., instance Luhn String where...
  2. Make it so that we can, on strings and integers, directly send them a message asking whether they represent valid luhn numbers (rather than passing them into a function).
    • i.e. this means instead of saying valid_luhn?("59"), we can say something like "59".valid_luhn?. This distinction may not be important for some languages, and in languages with UFCS (D, Rust, Nim) they are equivalent anyway, so implementing one admits the other.
    • this is equivalent to monkey-patching in Ruby, or a Ruby refinement.
    • this is equivalent to a Swift extension
    • this is equivalent to a Kotlin extension
    • this is equivalent to a C# extension method
    • this is equivalent to an Elixir protocol
    • there are so many languages supporting extension methods that I am having too hard of a time remembering and listing them all. You can feel free to add to this list.

So, many languages support these features and could ostensibly make the same exercise as those proposed. Would they want to apply these exact techniques to the Luhn exercise in particular I don't know, but we can discuss the right way.


Aside: I didn't realize until doing research for the above that Rust supports UFCS, but I guess it's logical that it does... please feel free to point out other languages with UFCS since I'm interested in language features.

@robkeim
Copy link
Contributor

robkeim commented Jan 17, 2017

@petertseng said:

I do want to ask whether an F#-specific exercise ever materialised, but I think I would have seen an x-common PR if it did, so I have to assume no.

There are no F# specific exercises today, however, I'm not sure if any have been suggested in the past.

@ErikSchierboom keep me honest here :)

@NobbZ
Copy link
Member

NobbZ commented Jan 17, 2017

i.e. this means instead of saying valid_luhn?("59"), we can say something like "59".valid_luhn?

This is just an implementation detail, which again is totally in the hand of the implementing track.

BUT! As you are already said elsewhere:

allow so that both strings and integers can be converted to this type.

THIS is the important and interesting part of your post. And let me rephrase it:

Can we extend the canonical tests in a way, that they allow optional generalisation over types?

@ErikSchierboom
Copy link
Member Author

As @robkeim said, we haven't added an F# specific exercise. I've just found out that there is also a lenses library for F#: Aether. We'll thus also be adding lens-person to the F# track, so the Haskell-specific text should indeed be dropped.

@IanWhitney
Copy link
Contributor

This is less about Luhn and more about a way to use the Rust exercises to teach Rust concepts. Luhn just seemed like a good candidate. The idea is:

  • Exercise 1: Figure out the domain logic, using a bare function
  • Exercise 2: Solve Exercise 1 again, this time using the more idiomatic Rust From trait
  • Exercise 3: Solve Exercise 1 again, this time by adding a custom traits to primitives

Other exercises could do similar things with whatever exercises fit their needs.

Since these type of exercises will be specific to the language track, it seems to me that it's better to not have to rely on the existence of metadata.

@petertseng
Copy link
Member

petertseng commented Jan 17, 2017

Can we extend the canonical tests in a way, that they allow optional generalisation over types?

This has been a long-standing question, and I've not come up with a good solution yet, instead only leaving notes in the JSON files: https://github.com/exercism/x-common/blob/master/exercises/react/canonical-data.json#L38 and https://github.com/exercism/x-common/blob/master/exercises/circular-buffer/canonical-data.json#L20 .

One thing I was wondering is whether it would be made unnecessarily difficult for statically typed languages to read the JSON file if in one case the values are strings and in the other case the values are integers, for example. We may not know this until some track runs into it, so I've only left it at that for now, but in the future we may have to discuss it more, perhaps when dealing with #336.

@Insti Insti reopened this Jan 18, 2017
@Insti
Copy link
Contributor

Insti commented Jan 18, 2017

Strict typing is a very language dependent concept, so I would argue that it does not belong in the canonical-data and should instead be dealt with some other way.

@ErikSchierboom
Copy link
Member Author

I'm with @Insti. The canonical-data should be language independent. If a language track decides to add some additional type-related features to an exercise, why not? However, this should not be reflected in the canonical-data IMHO, unless it is a feature shared by several languages and we can make a dedicated exercise for it.

@Insti
Copy link
Contributor

Insti commented Jan 18, 2017

I'd suggest that type handling should be its own exercise(s) and question whether it needs to be included in any other exercise.

If the exercise is about validating a number it surely doesn't make much difference algorithmically if the number is an integer or a string or some other specific type.

And if we're:

Exercise 1: Figure out the domain logic, using a bare function
Exercise 2: Solve Exercise 1 again, this time using the more idiomatic Rust From trait
Exercise 3: Solve Exercise 1 again, this time by adding a custom traits to primitives

Then it doesn't matter what the domain logic component is.

ErikSchierboom pushed a commit that referenced this issue Jan 19, 2017
At the time it was added (#97), indeed [Haskell][haskell] was the only
implementing track, and it was marked Haskell-specific.

However, the [Scala][scala] track has also implemented this exercise.
I predict it is confusing for Scala students to see "Haskell specific"
in the list of the Scala exercises. The proposal is to change it to
"specific to languages with immutable data".

[haskell]: exercism/haskell#84
[scala]: exercism/scala#157

Lenses can be a fit for any language that has immutable data and data
structures that can be nested.

In such a language, updating a deeply-nested field can be a lot of work,
but made easier with lenses. This exercise demonstrates the use of
lenses and is applicable to **any** language with immutable data, not
just Haskell.

The alternative considered was to use "functional programming" specific,
but the term "functional programming" is a little too broad. It's
altogether possible that a functional programming language could have
mutable data and a non-functional programming language could have
immutable data, so let's be precise about where lenses are helpful.

As of this writing, I do not believe any other exercise is
language-specific. Questions to this effect have been asked in:

* #352
* exercism/exercism#3113

If you are curious about having language-specific exercises, you may be
interested in exercism/DEPRECATED.trackler#22.
@petertseng
Copy link
Member

petertseng commented Feb 20, 2017

I'm not convinced there is much left to discuss here about language-specific exercises.

  • We discovered that there are currently no language-specific exercises in x-common
    • See http://exercism.io/languages/teco/todo (The "Unimplemented Exercises" list for any track without exercises) for support of the claim.
    • Currently each exercise is implemented by at least two tracks, with the exception of PaaS I/O (Go) and Rotational Cipher (Rust).
    • If you look at the descriptions, I argue that neither are specific to their implementing language...
    • though I will note that PaaS I/O was made specifically to fill a specific need that originated in the Go track, so if there is any claimant to being a language-specific exercise, it is that one!
  • We currently discuss in Allow a Track to define an exercise that is does not have a language-independent definition DEPRECATED.trackler#22 whether there could be, but they would be kept in the track repos, not in x-common
  • There is some discussion about generalisation over types, but it's not clear that such a thing will ever be essential to the problem at hand unless we have an exercise specifically about types.

@petertseng
Copy link
Member

Notice to all track maintainers:

With exercism/DEPRECATED.trackler#24, it is now possible to have track-specific exercises. Place the description.md and metadata.yml inside the exercise directory inside your track.

I recommend that this be documented.

@IanWhitney
Copy link
Contributor

(I'm documenting it, btw)

@ErikSchierboom
Copy link
Member Author

@IanWhitney Great!

@Insti
Copy link
Contributor

Insti commented Apr 21, 2017

Where can I find the documentation for this?

@Stargator
Copy link
Contributor

@IanWhitney Where's the documentation for this?

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

7 participants