Giter Club home page Giter Club logo

Comments (12)

cmcaine avatar cmcaine commented on September 27, 2024 1

from julia.

cmcaine avatar cmcaine commented on September 27, 2024

Hello!

Why do you particularly want to avoid calling replace in two places?

If you do want to call it just the once you can do so without a try/catch. I think what's tripping you up is that you can't reuse ISBN(s) in isvalid(ISBN, s) without a try/catch and yet you don't want to duplicate the code in the ISBN function. But what if you had a third function?

Does that help?

Regarding a hint in the description, I don't think we are pushing students to use replace only once or avoid try/catch, so I'm not sure we need one?

Anyone wanting to improve their solution can always request mentoring :)

Looking at the description, I think our main issue is that we don't specify the problem very completely (you have to read the tests for that).

We also suggest a truly horrendous bonus task: "Implement show(io::IO, isbn::ISBN) to print the ISBN in the standard format with dashes." Where to place the dashes depends on pages and pages of data about different worldwide publishers, etc cos each part of the ISBN is variable length.

We should probably remove that, tho I think that bit is only visible in the instructions.md that doesn't get used? I forget how that works.

from julia.

gpucce avatar gpucce commented on September 27, 2024

Hi thanks for the answer! I had not thought about that indeed, I really wanted to use those two together :)

However, just so I don't miss the point again with a third function I would need to use that function twice or can I avoid that?

The strange bonus track I have not noticed honestly so it should be hidden.

For sure I had to read the tests while doing the exercises otherwise the DomainError would have never crossed my mind.

from julia.

cmcaine avatar cmcaine commented on September 27, 2024

ISBN(s) and isvalid(ISBN, s) will each need to call your third function at least once each. Further details (not too spoilery) below.

The removal of the try/catch is simply by replacing a function that will throw an error with one that returns an error type.

I would implement this by defining Base.tryparse(::Type{ISBN}, s), but of course you don't need to add a method to that existing function you could write something like tryparse_isbn(s) or isbn_or_nothing(s) or whatever you'd like to call it.

from julia.

gpucce avatar gpucce commented on September 27, 2024

Thanks so much! This is the solution I didn't know existed :)

from julia.

cmcaine avatar cmcaine commented on September 27, 2024

Here's my solution just written and a comment:

# It doesn't make any sense to me for an ISBN to be a String - basically none of the String API makes sense for an ISBN.
# But the tests require this, so whatever.
struct ISBN{T} <: AbstractString
    s::T
end

Base.string(s::ISBN) = s.s

function Base.tryparse(::Type{ISBN}, s)
    acc = 0
    coeff = 10
    for c in s
        if c == '-'
            continue
        elseif isdigit(c)
            # c - '0' is a much faster version of parse(Int, c) when we know c is in '0':'9'.
            acc += (c - '0') * coeff
            coeff -= 1
        # Only the check "digit" is allowed to be 'X' (10)
        elseif c == 'X' && coeff == 1
            acc += 10
            coeff -= 1
        else
            # Invalid character
            return nothing
        end
    end
    if coeff != 0
        # String did not contain 10 "digits"
        return nothing
    elseif acc % 11 != 0
        # Check digit invalid
        return nothing
    else
        # Canonicalise the string in the simplest way:
        s = replace(s, '-' => "")
        return ISBN{typeof(s)}(s)
    end
end

function ISBN(s)
    x = tryparse(ISBN, s)
    if isnothing(x)
        throw(DomainError(s, "Invalid ISBN (wrong length, wrong checksum or invalid characters)"))
    else
        x
    end
end

Base.isvalid(::Type{ISBN}, s) = tryparse(ISBN, s) != nothing

macro isbn_str(s)
    ISBN(s)
end

Note that by using tryparse we lose the context for why parsing has failed. Arguably, the more natural way of expressing this in Julia would be to have ISBN(s) do the parsing and then just use a try/catch.

If you are particular fan of returning rather than throwing errors (e.g. if you come from Haskell or something) then you could do that by returning a more descriptive error type than nothing. E.g. you could just return DomainError(s, "invalid character") or something (using the exception struct as an error value).

And if you are iterating over the characters in the string you don't need to use replace in isvalid at all, so here's another way you can write it:

# It doesn't make any sense to me for an ISBN to be a String - basically none of the String API makes sense for an ISBN.
# But the tests require this, so whatever.
struct ISBN{T} <: AbstractString
    s::T

    function ISBN(s)
        if !isvalid(ISBN, s)
            throw(DomainError(s, "Invalid ISBN (wrong length, wrong checksum or invalid characters)"))
        else
            # Canonicalise the string in the simplest way:
            s = replace(s, '-' => "")
            new{typeof(s)}(s)
        end
    end
end

Base.string(s::ISBN) = s.s

function Base.isvalid(::Type{ISBN}, s)
    acc = 0
    coeff = 10
    for c in s
        if c == '-'
            continue
        elseif isdigit(c)
            # c - '0' is a much faster version of parse(Int, c) when we know c is in '0':'9'.
            acc += (c - '0') * coeff
            coeff -= 1
        # Only the check "digit" is allowed to be 'X' (10)
        elseif c == 'X' && coeff == 1
            acc += 10
            coeff -= 1
        else
            # Invalid character
            return false
        end
    end
    # s must contain 10 "digits" and check digit must be valid.
    return coeff == 0 && acc % 11 == 0
end

macro isbn_str(s)
    ISBN(s)
end

from julia.

SaschaMann avatar SaschaMann commented on September 27, 2024
# It doesn't make any sense to me for an ISBN to be a String - basically none of the String API makes sense for an ISBN.
# But the tests require this, so whatever.

isvalid is only defined on strings by default, which is why I think I added that back then. But I agree there's no real need for it, feel free to remove that test.

from julia.

SaschaMann avatar SaschaMann commented on September 27, 2024

Personally, I would define only a constructor and have it throw errors.

That sounds reasonable. Do you want to submit a PR to change it?

from julia.

gpucce avatar gpucce commented on September 27, 2024

If you want and there is no rush I can try to make the PR, I think I might have understood the point. Otherwise I will solve the exercise again after you change it!

from julia.

cmcaine avatar cmcaine commented on September 27, 2024

I made a PR at #504. Can't remember if @gpucce would have been notified about that.

from julia.

gpucce avatar gpucce commented on September 27, 2024

I think yes because I knew you had done it :) @cmcaine should I close the issue?

from julia.

cmcaine avatar cmcaine commented on September 27, 2024

I'll do it. Thanks for engaging!

from julia.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.