F# 如何使用类似printf的函数获得区域性感知输出?
有没有一种方法可以使用F#的F# 如何使用类似printf的函数获得区域性感知输出?,f#,printf,F#,Printf,有没有一种方法可以使用F#的sprintffloat格式和十进制逗号?如果这能奏效,那就太好了: sprintf "%,1f" 23.456 // expected: "23,456" 还是我只能用 编辑:我想要一个小数点分隔符。像大多数非英语国家一样使用它。看看Printf模块的源代码,它使用。我不认为printf类函数具有文化意识 如果您总是需要逗号,可以使用sprintf和string.Replace函数。如果您的代码依赖于区域性,那么最好使用ToString或String.Format
sprintf
float格式和十进制逗号?如果这能奏效,那就太好了:
sprintf "%,1f" 23.456
// expected: "23,456"
还是我只能用
编辑:我想要一个小数点分隔符。像大多数非英语国家一样使用它。看看
Printf
模块的源代码,它使用。我不认为printf类函数具有文化意识
如果您总是需要逗号,可以使用
sprintf
和string.Replace
函数。如果您的代码依赖于区域性,那么最好使用ToString
或String.Format
。这很痛苦,但您可以编写自己版本的sprintf
,完全满足您的要求:
open System
open System.Text.RegularExpressions
open System.Linq.Expressions
let printfRegex = Regex(@"^(?<text>[^%]*)((?<placeholder>%(%|((0|-|\+| )?([0-9]+)?(\.[0-9]+)?b|c|s|d|i|u|x|X|o|e|E|f|F|g|G|M|O|A|\+A|a|t)))(?<text>[^%]*))*$", RegexOptions.ExplicitCapture ||| RegexOptions.Compiled)
type PrintfExpr =
| K of Expression
| F of ParameterExpression * Expression
let sprintf' (c:System.Globalization.CultureInfo) (f:Printf.StringFormat<'a>) : 'a =
//'a has form 't1 -> 't2 -> ... -> string
let cultureExpr = Expression.Constant(c) :> Expression
let m = printfRegex.Match(f.Value)
let prefix = m.Groups.["text"].Captures.[0].Value
let inputTypes =
let rec loop t =
if Reflection.FSharpType.IsFunction t then
let dom, rng = Reflection.FSharpType.GetFunctionElements t
dom :: loop rng
else
if t <> typeof<string> then
failwithf "Unexpected return type: %A" t
[]
ref(loop typeof<'a>)
let pop() =
let (t::ts) = !inputTypes
inputTypes := ts
t
let exprs =
K(Expression.Constant(prefix)) ::
[for i in 0 .. m.Groups.["placeholder"].Captures.Count - 1 do
let ph = m.Groups.["placeholder"].Captures.[i].Value
let text = m.Groups.["text"].Captures.[i+1].Value
// TODO: handle flags, width, precision, other placeholder types, etc.
if ph = "%%" then yield K(Expression.Constant("%" + text))
else
match ph with
| "%f" ->
let t = pop()
if t <> typeof<float> && t <> typeof<float32> then
failwithf "Unexpected type for %%f placeholder: %A" t
let e = Expression.Variable t
yield F(e, Expression.Call(e, t.GetMethod("ToString", [| typeof<System.Globalization.CultureInfo> |]), [cultureExpr]))
| "%s" ->
let t = pop()
if t <> typeof<string> then
failwithf "Unexpected type for %%s placeholder: %A" t
let e = Expression.Variable t
yield F(e, e)
| _ ->
failwithf "unhandled placeholder: %s" ph
yield K (Expression.Constant text)]
let innerExpr =
Expression.Call(typeof<string>.GetMethod("Concat", [|typeof<string[]>|]), Expression.NewArrayInit(typeof<string>, exprs |> Seq.map (fun (K e | F(_,e)) -> e)))
:> Expression
let funcConvert =
typeof<FuncConvert>.GetMethods()
|> Seq.find (fun mi -> mi.Name = "ToFSharpFunc" && mi.GetParameters().[0].ParameterType.GetGenericTypeDefinition() = typedefof<Converter<_,_>>)
let body =
List.foldBack (fun pe (e:Expression) ->
match pe with
| K _ -> e
| F(p,_) ->
let m = funcConvert.MakeGenericMethod(p.Type, e.Type)
Expression.Call(m, Expression.Lambda(m.GetParameters().[0].ParameterType, e, p))
:> Expression) exprs innerExpr
Expression.Lambda(body, [||]).Compile().DynamicInvoke() :?> 'a
sprintf' (Globalization.CultureInfo.GetCultureInfo "fr-FR") "%s %f > %f" "It worked!" 1.5f -12.3
开放系统
打开System.Text.RegularExpressions
开放系统.Linq.Expressions
(0-0-9[0-9]+)(([0-0-9[0-0-9 10 10-9 10 10 10 10-9 10 10 10 10-9)10 10 10 10-9)10,([0-0-9 10-9 10 10-9+)(([0-0-9 10-9 10-9 10 10 10-9+)、b(0-0-0-9 10-9 10 10 10-9 9)10 10 10 10 10 10 10 10-10 10 10 10 10 10-10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10++++++++10)以及以及b(b(0-0-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-10-9)以及以及(0-10-10-10-10-10-10-10-9)10 10-9++10 10 10 10 10 10 10 10-9++10 10 10 10 10 10 tCapture | | | RegexOptions.Compiled)
类型PrintfExpr=
|表达方式
|参数表达式*表达式的F
让我们使用sprintf'(c:System.Globalization.CultureInfo)(f:Printf.StringFormat't2->…->字符串
让cultureExpr=Expression.Constant(c):>Expression
设m=printfRegex.Match(f.Value)
let prefix=m.Groups.[“text”]。捕获[0]。值
让输入类型=
让rec循环t=
如果Reflection.FSharpType.ist函数
让dom,rng=Reflection.FSharpType.GetFunctionElements t
dom::loop rng
其他的
如果不是,那么
failwithf“意外返回类型:%A”t
[]
裁判(loop typeofSorry,我误解了这个问题。我编辑了我的答案。因此,从源代码修改后,我可以生成一个sprintf
函数,该函数还包含一个CultureInfo参数?我编辑了标题和正文,以提高清晰度和可搜索性。如果它有错误,请随意回滚。因此,您是否建议使用String.Format代码>?:)+1表示纯粹的努力。