-
Notifications
You must be signed in to change notification settings - Fork 8
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
Handling of AbstractIrrational
#50
Changes from all commits
2a77eac
e19db39
bfac4e1
67ad47f
ddbc981
643dc79
f33aba0
34feb56
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,7 +18,7 @@ mutable struct DefaultSpec | |
DefaultSpec(c::AbstractChar) = new(Char(c), FormatSpec(c)) | ||
end | ||
|
||
const DEFAULT_FORMATTERS = Dict{DataType, DefaultSpec}() | ||
const DEFAULT_FORMATTERS = Dict{Union{DataType, UnionAll}, DefaultSpec}() | ||
|
||
# adds a new default formatter for this type | ||
default_spec!(::Type{T}, c::AbstractChar) where {T} = | ||
|
@@ -29,7 +29,12 @@ default_spec!(::Type{T}, ::Type{K}) where {T,K} = | |
(DEFAULT_FORMATTERS[T] = DEFAULT_FORMATTERS[K]; nothing) | ||
|
||
# seed it with some basic default formatters | ||
for (t, c) in [(Integer,'d'), (AbstractFloat,'f'), (AbstractChar,'c'), (AbstractString,'s')] | ||
ComplexInteger = Complex{T} where T<:Integer | ||
ComplexFloat = Complex{T} where T<:AbstractFloat | ||
ComplexRational = Complex{T} where T<:Rational | ||
for (t, c) in [(Integer,'d'), (AbstractFloat,'f'), (AbstractChar,'c'), (AbstractString,'s'), | ||
(ComplexInteger,'d'), (ComplexFloat,'f'), (Number,'S'), (AbstractIrrational,'S'), | ||
(Rational,'S'), (ComplexRational,'S')] | ||
default_spec!(t, c) | ||
end | ||
|
||
|
@@ -62,10 +67,16 @@ end | |
# methods to get the current default objects | ||
# note: if you want to set a default for an abstract type (i.e. AbstractFloat) | ||
# you'll need to extend this method like here: | ||
default_spec(::Type{<:Integer}) = DEFAULT_FORMATTERS[Integer] | ||
default_spec(::Type{<:AbstractFloat}) = DEFAULT_FORMATTERS[AbstractFloat] | ||
default_spec(::Type{<:AbstractString}) = DEFAULT_FORMATTERS[AbstractString] | ||
default_spec(::Type{<:AbstractChar}) = DEFAULT_FORMATTERS[AbstractChar] | ||
default_spec(::Type{<:Integer}) = DEFAULT_FORMATTERS[Integer] | ||
default_spec(::Type{<:AbstractFloat}) = DEFAULT_FORMATTERS[AbstractFloat] | ||
default_spec(::Type{<:AbstractString}) = DEFAULT_FORMATTERS[AbstractString] | ||
default_spec(::Type{<:AbstractChar}) = DEFAULT_FORMATTERS[AbstractChar] | ||
default_spec(::Type{<:AbstractIrrational}) = DEFAULT_FORMATTERS[AbstractIrrational] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only the one for |
||
default_spec(::Type{<:Number}) = DEFAULT_FORMATTERS[Number] | ||
default_spec(::ComplexInteger) = DEFAULT_FORMATTERS[ComplexInteger] | ||
default_spec(::ComplexFloat) = DEFAULT_FORMATTERS[ComplexFloat] | ||
default_spec(::Rational) = DEFAULT_FORMATTERS[Rational] | ||
default_spec(::ComplexRational) = DEFAULT_FORMATTERS[ComplexRational] | ||
|
||
default_spec(::Type{T}) where {T} = | ||
get(DEFAULT_FORMATTERS, T) do | ||
|
@@ -176,7 +187,7 @@ function fmt end | |
# TODO: do more caching to optimize repeated calls | ||
|
||
# creates a new FormatSpec by overriding the defaults and passes it to pyfmt | ||
# note: adding kwargs is only appropriate for one-off formatting. | ||
# note: adding kwargs is only appropriate for one-off formatting. | ||
# normally it will be much faster to change the fmt_default formatting as needed | ||
function fmt(x; kwargs...) | ||
fspec = fmt_default(x) | ||
|
@@ -200,3 +211,6 @@ function fmt(x, syms::Symbol...; kwargs...) | |
d = _add_kwargs_from_symbols(kwargs, syms...) | ||
fmt(x; d...) | ||
end | ||
|
||
#fmt_default!(AbstractIrrational, 's', :right) | ||
#fmt_default!(Number, 's', :right) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,25 +9,26 @@ | |
# width ::= <integer> | ||
# prec ::= <integer> | ||
# type ::= 'b' | 'c' | 'd' | 'e' | 'E' | 'f' | 'F' | 'g' | 'G' | | ||
# 'n' | 'o' | 'x' | 'X' | 's' | ||
# 'n' | 'o' | 'x' | 'X' | 's' | 'S' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I really don't want any non-standard characters added, |
||
# | ||
# Please refer to http://docs.python.org/2/library/string.html#formatspec | ||
# for more details | ||
# | ||
|
||
## FormatSpec type | ||
|
||
const _numtypchars = Set(['b', 'd', 'e', 'E', 'f', 'F', 'g', 'G', 'n', 'o', 'x', 'X']) | ||
const _numtypchars = Set(['b', 'd', 'e', 'E', 'f', 'F', 'g', 'G', 'n', 'o', 'x', 'X', 'S']) | ||
|
||
_tycls(c::AbstractChar) = | ||
(c == 'd' || c == 'n' || c == 'b' || c == 'o' || c == 'x') ? 'i' : | ||
(c == 'e' || c == 'f' || c == 'g') ? 'f' : | ||
(c == 'c') ? 'c' : | ||
(c == 's') ? 's' : | ||
(c == 'S') ? 'S' : | ||
error("Invalid type char $(c)") | ||
|
||
struct FormatSpec | ||
cls::Char # category: 'i' | 'f' | 'c' | 's' | ||
cls::Char # category: 'i' | 'f' | 'c' | 's' | 'S' | ||
typ::Char | ||
fill::Char | ||
align::Char | ||
|
@@ -84,7 +85,7 @@ end | |
|
||
## parse FormatSpec from a string | ||
|
||
const _spec_regex = r"^(.?[<>])?([ +-])?(#)?(\d+)?(,)?(.\d+)?([bcdeEfFgGnosxX])?$" | ||
const _spec_regex = r"^(.?[<>])?([ +-])?(#)?(\d+)?(,)?(.\d+)?([bcdeEfFgGnosxXS])?$" | ||
|
||
function FormatSpec(s::AbstractString) | ||
# default spec | ||
|
@@ -164,27 +165,38 @@ _srepr(x) = repr(x) | |
_srepr(x::AbstractString) = x | ||
_srepr(x::AbstractChar) = string(x) | ||
_srepr(x::Enum) = string(x) | ||
@static if VERSION < v"1.2.0-DEV" | ||
_srepr(x::Irrational{sym}) where {sym} = string(sym) | ||
end | ||
|
||
function printfmt(io::IO, fs::FormatSpec, x) | ||
cls = fs.cls | ||
ty = fs.typ | ||
if cls == 'i' | ||
ix = Integer(x) | ||
ix = x | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You've introduced type instability here, and it's better to just get an exception if the format class isn't valid for the given type. |
||
try | ||
ix = Integer(x) | ||
catch | ||
end | ||
ty == 'd' || ty == 'n' ? _pfmt_i(io, fs, ix, _Dec()) : | ||
ty == 'x' ? _pfmt_i(io, fs, ix, _Hex()) : | ||
ty == 'X' ? _pfmt_i(io, fs, ix, _HEX()) : | ||
ty == 'o' ? _pfmt_i(io, fs, ix, _Oct()) : | ||
_pfmt_i(io, fs, ix, _Bin()) | ||
elseif cls == 'f' | ||
fx = float(x) | ||
fx = x | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above, better for this to get an exception, instead of slowing this down by introducing type instability, and covering up what might be useful information for the programmer. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not so sure whether we should care about type stability here. (I am definitely not an expert here!)
I think, you misinterpreted my code. I have added new less specific methods, e.g. The last argument of that method is an anonymous formatting routine for the specific type ('i', 'e' or 'f') where the width of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That's the problem, because depending on the length, it may truncate important information. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't see this: |
||
try | ||
fx = float(x) | ||
catch | ||
end | ||
if isfinite(fx) | ||
ty == 'f' || ty == 'F' ? _pfmt_f(io, fs, fx) : | ||
ty == 'e' || ty == 'E' ? _pfmt_e(io, fs, fx) : | ||
error("format for type g or G is not supported yet (use f or e instead).") | ||
else | ||
_pfmt_specialf(io, fs, fx) | ||
end | ||
elseif cls == 's' | ||
elseif cls == 's' || cls == 'S' | ||
_pfmt_s(io, fs, _srepr(x)) | ||
else # cls == 'c' | ||
_pfmt_s(io, fs, Char(x)) | ||
|
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.
Why do you want a subtype here? Why not just all anything of type Complex?
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 wanted automatic
Integer
formatting for allComplex{Integer}
types in one go, that's why I changed the dict type tp Union{DataType,UnionAll}.So I can write
fmt_default!(Complex{T} where T<:Integer}
and alsodefault_spec!(Complex{T} where T<:Integer}, 'f')
Otherwise we would need to to this for all subtypes individually.
The same hold for any other package that has a similar type system without an abstract supertype.
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.
What this means is that you have to set up defaults for pretty much any arbitrary
Complex
number, which I don't think is desirable behavior.