Skip to content
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

dibs: I will implement exercise atbash-cipher #72

Merged
merged 5 commits into from Oct 18, 2016
Merged

Conversation

dvberkel
Copy link
Contributor

@dvberkel dvberkel commented Oct 7, 2016

Work in progress

@dvberkel
Copy link
Contributor Author

dvberkel commented Oct 7, 2016

@stevejb71 I would love you feedback on this. I might have gone overboard and missing some Core library functions for this exercises.

Besides that, two test cases fail, and I can't figure out why? Would appreciate any pointers you might have.

@stevejb71
Copy link
Contributor

Happy to give feedback. I'll take a look later today (Hong Kong time).

| (_, []) -> []
| (_, _::xs) -> drop (n-1) xs

let rec group n l =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has a bug: if the length of the list is 0 then it returns [[]], it should return []. That should fix the broken tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch! Will definitely look into that.

I should have tested these methods as well, but I didn't want to enforce an implementation direction.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You were right not to publish tests for these internal function as they are implementation details. I just run adhoc tests in utop in this case.

| 'a' .. 'z' | '0' .. '9' -> true
| _ -> false

let explode s =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The signature of this function is not immediately obvious (at least to me!). A Haskell convention is to provide type signatures on top level functions in a module - that gives useful, and compiler checked, documentation. I'd favour the same in Ocaml code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was not sure what the OCaml convention is. I myself would rather provide type signatures for everything, although this takes away the benefit of type inference.

I will provide the type signatures.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have troubles providing an inline signature because of the use of function. Because it is an implementation detail, I can't provide the signature in the mli-file.

Do you have a tip?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know of a way of providing a signature in this case. Either rewrite if you think adding a signature is worth it, or leave as is.

else
(take n l) :: (group n (drop n l))

let encode ?block_size:(block_size = 5) word =
Copy link
Contributor

@stevejb71 stevejb71 Oct 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps text is better than word - the input can be more than 1 word.

Also, the optional parameter can be provided more simply:
?(block_size = 5)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, text is a better name.

I will adopt your improvement for the optional parameter

let filtered_characters = List.filter is_encodable characters in
let groups = group block_size filtered_characters in
let preprocessed_words = List.map implode groups in
let words = List.map (fun (word) -> (String.map substitute word)) preprocessed_words in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might as well take advantage of currying here:
let words = List.map (String.map substitute) preprocessed_words in

In any event, you don't need the brackets around the word parameter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! That is a very good suggestion

@@ -0,0 +1,5 @@
(* Encoding from English to atbash cipher *)
Copy link
Contributor

@stevejb71 stevejb71 Oct 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default value block_size is 5 according to the README. You might want to specify that in the comment. (I don't think there is anyway to specify a default value for a parameter in the .mli code.)


let ae exp got _test_ctxt = assert_equal ~printer:String.to_string exp got

let tests =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should add a couple of tests with a different block size.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly!

@@ -0,0 +1,57 @@
let substitute = function
Copy link
Contributor

@stevejb71 stevejb71 Oct 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are not using Core here. That would make implementation a touch easier (no need to rewrite drop and take).

Do you prefer not to use it, or was it an oversight?

Copy link
Contributor Author

@dvberkel dvberkel Oct 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was an oversight. Implementing take and drop distracts from the actual exercise.

Besides that, seeing that I made an incorrect implementation, I am in favour of _drop_ping (pun intended) the custom implementation for the ones in Core

@stevejb71
Copy link
Contributor

@dvberkel - I added a few comments - one of them includes how to fix the tests. Let me know when you are done making the changes you accept, and I can re-review.

@dvberkel
Copy link
Contributor Author

dvberkel commented Oct 8, 2016

@stevejb71 thanks for your review. They are very worthwhile. I will improve the code with your suggestions later today. I will drop you a line when I am finished

@dvberkel
Copy link
Contributor Author

dvberkel commented Oct 8, 2016

@stevejb71 I updated the exercise with your suggestion. I couldn't provide a type signature for the substitute function. The function keyword and my suggestion kept conflicting. Do you have a solution?

@@ -1,3 +1,5 @@
open Core
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

open Core.Std instead.

Char.code becomes Char.to_int
Char.chr becomes Char.of_int_exn (functions throwing exceptions are documented like this consistently in Core).

[l]
else
(take n l) :: (group n (drop n l))
(Core_list.take l n) :: (group n (Core_list.drop l n))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you open Core.Std, then you have List.take and List.drop instead.

@stevejb71
Copy link
Contributor

I added a few comments to your last commit, but they are just suggestions for improvement in the non-public part of the code.

Given you have the tests passing now, I'd be happy to merge if you can just add a few tests with different block sizes (I think that is important as it is on the public interface).

@dvberkel
Copy link
Contributor Author

dvberkel commented Oct 9, 2016

I adopted your suggestion. Even though the code is not part of the public interface, it is important to show idiomatic code.

@dvberkel
Copy link
Contributor Author

@stevejb71 How are these changes looking? Care to give your go on them?

@dvberkel
Copy link
Contributor Author

I rebased in order to incorporate the latest changes

Copy link
Contributor

@stevejb71 stevejb71 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only remaining issuesl is about a test on a non standard block size. I saw a conversation about this on the canonical data, was it decided this test was not worth adding?

@dvberkel
Copy link
Contributor Author

I opened that issue and it received not a lot of attention. The only comment was that it w as OK the way it is. That is why I did not add other tests.

We could decide otherwise and still test other block sizes. @stevejb71 what do you think?

@stevejb71
Copy link
Contributor

I think we should add a test. 1 seems a bit of an edge case which would be good to test.

@dvberkel
Copy link
Contributor Author

I will add a test with a different block size

Two test cases fail, but I am uncertain why. To my, even on close
inspection they seem the same. But I am dyslectic, so what do I know
There is one outstanding improvement. I.e. provide type signature for
substitute. I had troubles providing the correct syntax with the
`function` keyword
@dvberkel
Copy link
Contributor Author

@stevejb71 added a test with a different block size

@stevejb71 stevejb71 merged commit aadf01d into master Oct 18, 2016
@dvberkel dvberkel deleted the atbash-cipher branch October 19, 2016 07:50
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

Successfully merging this pull request may close these issues.

None yet

2 participants