Closed neenjaw closed 4 years ago
Some questions from me:
1) How do the functions get_in
and update_in
relate to this exercise? Should be covered by it or not? And Access.key
?
2) Lists need to be avoided in this exercise because they do not support the access behavior. If we compromised and said "use Enum.at", we would be giving a bad example as lists are not meant for random access. Correct?
3) I have no idea about basketball. How can "lots of data" about a basketball team look like? There's this example in JS but I'm not sure how to translate it well into Elixir to avoid lists:
const team = {
players: [
{
name: "Becky",
position: "Point guard"
},
{
name: "Maya",
position: "Center"
}
]
};
Good questions:
I'm not sure get_in
or update_in
do directly unless we want to add that as a subsequent task. Which might be a good thing since they are useful and common. Access.key
is the static access operator
reference in the out-of-scope, I think that might work better once structs are introduced.
We could avoid it if that is what works best. This problem is taken from the JS reseach problem, which can sometimes be a bit tricky since they are open ended without guidance, but here we have the opportunity to break problems down to guide students through tasks.
If we didn't want to avoid it, we could place an arbitrary condition on the keys
that any numeric key
is actually nth
element of a list. This might be counter productive since numbers can be keys in a map structure.
For data there could be:
basketball_team = %{
players: [
%{
name: "Becky",
position: "Point guard",
player_number: 98,
average_points_per_game: 6.8,
games_played: 12
},
%{
name: "Maya",
position: "Center",
player_number: 34,
average_points_per_game: 6.8,
games_played: 4
}
],
coach: "Chris Marlin",
sponsors: "Dashbit"
}
This is a pretty good list of them here: https://en.wikipedia.org/wiki/Basketball_statistics
I think I will try to tackle this one, then going to spend some time making up some more issues.
It's interesting, part 1 of that basket ball problem is very easy (traversing the list map keys)
def extract(data, path) do
paths = String.split(path, ".", trim: true)
do_extract(data, paths)
end
def do_extract(nil, _), do: nil
def do_extract(data, []), do: data
def do_extract(data, [path|next]) do
do_extract(data[path], next)
end
But part two is kind of a nastier one for students I think because lets suppose:
# Team data
data = %{ "coaches" => [%{ "name" => "Jane" }], "name" => "Hoop Masters" }
# Path to extract
search_string = "coaches[0].name"
getting coach[0]
is easy as an extension to part 1. But then how to structure the exercise to separate coach
from [0]
and then how to get 0
from [0]
.
You could:
[x]
then returning all of the digits at x
, but then you also need to split the string to use the coaches
key[
then split at that pointWhat I am trying to get across is that I think it is much harder to do that I thought and my thoughts about the actual prerequisites is much larger than i describe above:
So some questions I am posing:
How much can I assume a student knows about regex so that we don't have to write a novel about regex parsing? How much can I expect a student to do? (e.g. write a string parser with accumulators, etc.) I think the v2 answer would be "write a string parser" then you'd hash it out with a mentor, but I don't think that's the v3 approach here.
So why?
I think for someone coming from javascript, they are going to want a way to write "string".indexOf("s")
and get a discrete answer to then "string".substring(0, i)
, which elixir should have a robust analogous way to translate that idea from one language to another.
I am just not sure which is the right way to do this for maximum benefit.
So I'm going to put out the :bat:-signal! @Cohen-Carlisle @chriseyre2000 @NobbZ @angelikatyborska @ErikSchierboom
How much can I assume a student knows about regex so that we don't have to write a novel about regex parsing?
I'd say: don't assume that the student knows anything about regular expressions actually, as I know many people actually don't know much about regular expressions.
What I am trying to get across is that I think it is much harder to do that I thought and my thoughts about the actual prerequisites is much larger than i describe above:
Perhaps this would suggest changing this part of the exercise a bit to make it better suited for Elixir?
I think for someone coming from javascript, they are going to want a way to write "string".indexOf("s") and get a discrete answer to then "string".substring(0, i), which elixir should have a robust analogous way to translate that idea from one language to another.
This is hard to do in Elixir?
I have no idea about basketball. How can "lots of data" about a basketball team look like?
I can help with this. Ping me whenever you want some basketball information or suggestions.
I'd say: don't assume that the student knows anything about regular expressions actually, as I know many people actually don't know much about regular expressions.
:+1: Ok, so I guess I'll plan for a regex exercise (or two) to precede this one.
Perhaps this would suggest changing this part of the exercise a bit to make it better suited for Elixir?
Agreed, I am thinking it will come to that
This is hard to do in Elixir?
I wouldn't say hard, but (at least I) don't know a direct translation of this idea from C-family languages without going to an erlang function (:binary.match
). There is often more of a focus to look at solving the intended problem (edit) in a more declarative way, or just by using a regex.
An interesting discussion here on Stack Overflow
But I think sleeping on this problem led me to this solution:
s = "coaches[0]"
[key, trailing] = String.split(s, "[", parts: 2)
index = String.trim_trailing(trailing, "]")
I can help with this. Ping me whenever you want some basketball information or suggestions.
:+1:
What if we completely avoid lists in this exercise? It's supposed to teach about access behavior, but lists don't support it. Lists could be replaced with maps like this:
["a", "b", "c"]
# becomes
%{
"1" => "a",
"2" => "b",
"3" => "c"
}
And then also reformat keys "coaches[0].name"
-> "coaches.0.name"
to simplify parsing.
The philosophy of concept exercises is that everything in the exercise that is not related to the new concepts should be as simple as possible, right?
BTW., I am a bit worried about keyword lists. If we decide to include them using this story, would that mean telling students to take a string "key1.key2.key3", split it, and then transform it to atoms? Not the best lesson. Maybe it would be easier to come up with a new story, more suited for Elixir?
Yes, I think that is a good point, dynamically creating atoms is an anti-pattern to avoid.
I think the best thing to do is change the narrative to avoid this.
I withdraw the 🦇 -signal! Thanks for the help!
@team_data = %{
"coach" => %{
"first_name" => "Jane",
"last_name" => "Brown"
},
"team_name" => "Hoop Masters",
"players" => %{
"99" => %{
"first_name" => "Amalee",
"last_name" => "Tynemouth",
"email" => "atynemouth0@yellowpages.com"
},
"98" => %{
"first_name" => "Tiffie",
"last_name" => "Derle",
"email" => "tderle1@vimeo.com"
},
"23" => %{
"first_name" => "Garfield",
"last_name" => "Beeho",
"email" => nil
},
"36" => %{
"first_name" => "Clio",
"last_name" => "Serfati",
"email" => "cserfati3@comsenz.com"
},
"42" => %{
"first_name" => "Conchita",
"last_name" => "Elham",
"email" => "celham4@wikia.com"
},
"61" => %{
"first_name" => "Noel",
"last_name" => "Fawlkes",
"email" => "nfawlkes5@yahoo.co.jp"
},
"53" => %{
"first_name" => "Lucine",
"last_name" => "Russel",
"email" => "lrussel6@fotki.com"
},
"12" => %{
"first_name" => "Andy",
"last_name" => "Napoli",
"email" => "anapoli7@goodreads.com"
},
"9" => %{
"first_name" => "Ivar",
"last_name" => "Longson",
"email" => "ilongson8@timesonline.co.uk"
},
"32" => %{
"first_name" => "Deni",
"last_name" => "Lidster",
"email" => nil
}
}
}
I think I'll adapt the story to work with map string keys, and also touch on get_in
and put_in
This issue describes how to implement the
access-behavior
concept exercise for the Elixir track.🔗 How to help
Getting started
Please please please read the docs before starting. Posting PRs without reading these docs will be a lot more frustrating for you during the review cycle, and exhaust Exercism's maintainers' time. So, before diving into the implementation, please read up on the following documents:
Please also watch the following video:
Goal
The goal of this exercise is to teach how to use the access behavior to retrieve data from nested datastructures which implement the behavior. Out of the box, maps and keyword lists implement the access behavior.
Learning objectives
Out of scope
Concepts
access-behavior
Prerequisites
keyword-lists
maps
strings
pattern-matching
Narrative for exercise
Following the story outlined here, students should implement the task.
The task should be broken into sub-components which then culminate in the lesson.
Resources to refer to
Hints
After
Representer
Analyzer
Actionable items 🔗
looking for help in a few ways, and I am here to help you through getting this exercise off the ground:
For a first phase review we need:
Thanks for considering!
Need Help?
If you have any questions while implementing the exercise, please post the questions as comments in this issue.