-
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
Hh/general numbers #52
base: master
Are you sure you want to change the base?
Changes from 7 commits
d2dafff
3c88392
ed836bd
4a958ee
7d43657
874d042
cf67f99
4479a8a
d07f241
314a4fb
38e386a
82b9b43
befc01c
ab0bdac
7598556
0233e95
9e1d553
0eb2a8c
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 |
---|---|---|
|
@@ -29,7 +29,7 @@ function DefaultSpec(c::AbstractChar, syms...; kwargs...) | |
end | ||
end | ||
|
||
const DEFAULT_FORMATTERS = Dict{DataType, DefaultSpec}() | ||
const DEFAULT_FORMATTERS = Dict{Type{<:Any}, DefaultSpec}() | ||
|
||
# adds a new default formatter for this type | ||
default_spec!(::Type{T}, c::AbstractChar) where {T} = | ||
|
@@ -73,12 +73,21 @@ 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: | ||
|
||
const ComplexInteger = Complex{<:Integer} | ||
const ComplexFloat = Complex{<:AbstractFloat} | ||
const ComplexRational = Complex{<:Rational} | ||
|
||
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] | ||
default_spec(::Type{<:Rational}) = DEFAULT_FORMATTERS[Rational] | ||
default_spec(::Type{<:Number}) = DEFAULT_FORMATTERS[Number] | ||
default_spec(::ComplexInteger) = DEFAULT_FORMATTERS[ComplexInteger] | ||
default_spec(::ComplexFloat) = DEFAULT_FORMATTERS[ComplexFloat] | ||
default_spec(::ComplexRational) = DEFAULT_FORMATTERS[ComplexRational] | ||
|
||
default_spec(::Type{T}) where {T} = | ||
get(DEFAULT_FORMATTERS, T) do | ||
|
@@ -189,7 +198,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) | ||
|
@@ -220,9 +229,13 @@ end | |
for (t, c) in [(Integer,'d'), | ||
(AbstractFloat,'f'), | ||
(AbstractChar,'c'), | ||
(AbstractString,'s')] | ||
(AbstractString,'s'), | ||
(ComplexInteger,'d'), | ||
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. For now, please remove the separate |
||
(ComplexFloat,'f')] | ||
default_spec!(t, c) | ||
end | ||
|
||
default_spec!(Number, 's', :right) | ||
default_spec!(Rational, 's', :right) | ||
default_spec!(AbstractIrrational, 's', :right) | ||
default_spec!(ComplexRational, 's', :right) | ||
default_spec!(Number, 's', :right) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
# core formatting functions | ||
export fmt_Number | ||
|
||
### auxiliary functions | ||
|
||
|
@@ -262,3 +263,42 @@ function _pfmt_specialf(out::IO, fs::FormatSpec, x::AbstractFloat) | |
end | ||
end | ||
|
||
function _pfmt_Number_f(out::IO, fs::FormatSpec, x::Number, _pf::Function) | ||
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. These still have the issues that I mentioned before. |
||
fsi = FormatSpec(fs, width = -1) | ||
f = x->begin | ||
fx = AbstractFloat(x) # not float(x), this should error out, if conversion is not possible | ||
io = IOBuffer() | ||
_pf(io, fsi, fx) | ||
String(take!(io)) | ||
end | ||
s = fmt_Number(x, f) | ||
_pfmt_s(out, fs, s) | ||
end | ||
|
||
function _pfmt_Number_i(out::IO, fs::FormatSpec, x::Number, op::Op, _pf::Function) where {Op} | ||
fsi = FormatSpec(fs, width = -1) | ||
f = x->begin | ||
ix = Integer(x) | ||
io = IOBuffer() | ||
_pf(io, fsi, ix, op) | ||
String(take!(io)) | ||
end | ||
s = fmt_Number(x, f) | ||
_pfmt_s(out, fs, s) | ||
end | ||
|
||
function _pfmt_i(out::IO, fs::FormatSpec, x::Number, op::Op) where {Op} | ||
_pfmt_Number_i(out, fs, x, op, _pfmt_i) | ||
end | ||
|
||
function _pfmt_f(out::IO, fs::FormatSpec, x::Number) | ||
_pfmt_Number_f(out, fs, x, _pfmt_f) | ||
end | ||
|
||
function _pfmt_e(out::IO, fs::FormatSpec, x::Number) | ||
_pfmt_Number_f(out, fs, x, _pfmt_e) | ||
end | ||
|
||
function fmt_Number(x::Complex, f::Function) | ||
s = f(real(x)) * (imag(x) >= 0 ? " + " : " - ") * f(abs(imag(x))) * "im" | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -164,25 +164,42 @@ _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) | ||
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()) | ||
try | ||
ix = Integer(x) | ||
ty == 'd' || ty == 'n' ? _pfmt_i(io, fs, ix, _Dec()) : | ||
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. Code smell here - shouldn't have a bunch of copy-paste. 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 afraid that I didn't completely get what you have in mind. We can't go directly to If we have a composed type like So my idea was:
Due to this fallback, I think, it is ok to accept Example: EDIT: 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. For complex numbers, you could use the defaults for "d" based on the type For example: in the default dictionary, have simply an entry I'm looking for methods that don't just simply solve your problem for printing complex numbers, but also handle it in a more generic, extensible fashion. 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. One thing you may not have noticed, the C-style formatted strings (i.e. |
||
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()) | ||
catch | ||
ty == 'd' || ty == 'n' ? _pfmt_i(io, fs, x, _Dec()) : | ||
ty == 'x' ? _pfmt_i(io, fs, x, _Hex()) : | ||
ty == 'X' ? _pfmt_i(io, fs, x, _HEX()) : | ||
ty == 'o' ? _pfmt_i(io, fs, x, _Oct()) : | ||
_pfmt_i(io, fs, x, _Bin()) | ||
end | ||
elseif cls == 'f' | ||
fx = float(x) | ||
if isfinite(fx) | ||
ty == 'f' || ty == 'F' ? _pfmt_f(io, fs, fx) : | ||
ty == 'e' || ty == 'E' ? _pfmt_e(io, fs, fx) : | ||
try | ||
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 - if it can't get converted to something that is |
||
fx = float(x) | ||
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 | ||
catch | ||
ty == 'f' || ty == 'F' ? _pfmt_f(io, fs, x) : | ||
ty == 'e' || ty == 'E' ? _pfmt_e(io, fs, x) : | ||
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' | ||
_pfmt_s(io, fs, _srepr(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.
Again, you are confusing passing an instance of a particular type, with passing the type itself.
You need to have
::Type{<:Complex}
.I think it's best to work on making any complex type work at first, before trying to add the capability of having separate defaults for different parameterized Complex types.