-
-
Notifications
You must be signed in to change notification settings - Fork 402
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
New concept exercise top-secret
(concept: ast
)
#930
Conversation
Glad my idea inspired you so much :) |
@jiegillet the instructions, tests, stubs, and exemplar should all be "finished". It would be great if you could try to solve the exercise by following the instructions without looking at the exemplar first and let me know if they make sense, maybe even suggest hints based on your own experience 🙂 I will work on the introduction, hints, and everything else that needs to be finished soon. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome exercise. Here is my solution without looking at yours:
defmodule TopSecret do
def to_ast(string) do
Code.string_to_quoted!(string)
end
@def_ops [:def, :defp]
# this case I learned the hard way recently, but it might be too mean to include a case like this?
def decode_secret_message_part({op, _, [{:when, _, [{name, _, args} | _]} | _]} = ast, acc)
when op in @def_ops and is_list(args) do
acc = add_part(name, length(args), acc)
{ast, acc}
end
def decode_secret_message_part({op, _, [{name, _, args} | _]} = ast, acc)
when op in @def_ops and is_list(args) do
acc = add_part(name, length(args), acc)
{ast, acc}
end
def decode_secret_message_part(ast, acc) do
{ast, acc}
end
def decode_secret_message(string) do
{_, message} =
string
|> to_ast()
|> Macro.prewalk([], &decode_secret_message_part/2)
message
|> Enum.reverse()
|> Enum.join()
end
defp add_part(name, arity, acc) do
name
|> to_string()
|> String.slice(0, arity)
|> then(&[&1 | acc])
end
end
Co-authored-by: Jie <jie.gillet@gmail.com>
Hmm. Actually I like the idea of including a case for |
Thank you for contributing to Based on the files changed in this PR, it would be good to pay attention to the following details when reviewing the PR:
Automated comment created by PR Commenter 🤖. |
@@ -0,0 +1,40 @@ | |||
# About |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I gave up on writing a custom about.md
and just copy-pasted introduction.md
because I have doubts about how many students actually read those and I'm low on time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we will need to circle back to it once we have quote/unquote and macros concepts anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great!
I left a couple of comments for small things.
concepts/ast/about.md
Outdated
|
||
The ability to represent code as an AST is at the heart of metaprogramming in Elixir. _Macros_, which is a way to write Elixir code that produces Elixir code, work by returning ASTs as output. | ||
|
||
Another use case for ASTs is static code analysis, like Exercism's own tool, the Analyzer, which you might already known as the little bot that leaves comments on your solutions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another use case for ASTs is static code analysis, like Exercism's own tool, the Analyzer, which you might already known as the little bot that leaves comments on your solutions. | |
Another use case for ASTs is static code analysis, like Exercism's own tool, the Analyzer, which you might already know as the little bot that leaves comments on your solutions. |
@@ -0,0 +1,40 @@ | |||
# About |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we will need to circle back to it once we have quote/unquote and macros concepts anyway.
@@ -596,6 +596,23 @@ | |||
"dates-and-time" | |||
], | |||
"status": "beta" | |||
}, | |||
{ | |||
"slug": "top-secret", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add the prerequisite to dot-dsl
too.
- The AST node that contains the function's name also contains the function's argument list as the third element. | ||
- The exact pattern to match an AST node that defines a function and get its name and arguments is: `{op, _, [{name, _, arguments} | _]} when op in [:def, :defp]`. | ||
- The arity of a function is the length of its argument list. | ||
- There is a [built-in function in the `String` module][string-slice] that can get the first `n` characters from a string. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add one more hint:
- There is a [built-in function in the `String` module][string-slice] that can get the first `n` characters from a string. | |
- There is a [built-in function in the `String` module][string-slice] that can get the first `n` characters from a string. | |
- A function without arguments written without parentheses will not have a list as argument but an atom. |
|
||
## 5. Decode the full secret message | ||
|
||
- There is a [built-in function][macro-prewalk] that can visit each node in an AST with an accumulator. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more:
- There is a [built-in function][macro-prewalk] that can visit each node in an AST with an accumulator. | |
- There is a [built-in function][macro-prewalk] that can visit each node in an AST with an accumulator. | |
- Use the function `to_ast/1` that you implemented in the first task to create the AST. |
I'll merge this in an hour or so 🤞 it feels much more stressful to add new exercises when v3 is already live. |
@jiegillet I loved your idea so much that I immediately started working on it :) this is just the example solution, I will work on the test suite next. Not necessary to review yet, but I just wanted to signal I'm working on it.