gpt4 book ai didi

.net - F# printf 编译器魔法

转载 作者:行者123 更新时间:2023-12-01 15:54:51 24 4
gpt4 key购买 nike

在 F# 中,编译器显然做了一些魔术来完成这项工作:

printfn "%i %i" 6 7 ;; // good
printfn "%i %i" 6 7 8;; // error

它是如何做到的?有什么方法可以在语言中实现类似的行为?

最佳答案

遗憾的是,这一点“魔法”(正如您所说的那样)被硬编码到 F# 编译器中。您可以扩展编译器,但结果将是非标准 F#。

这是处理该问题的特定代码(它不太可读,但这就是 F# 编译器的编写方式):

and TcConstStringExpr cenv overallTy env m tpenv s  =

if (AddCxTypeEqualsTypeUndoIfFailed env.DisplayEnv cenv.css m overallTy cenv.g.string_ty) then
mkString cenv.g m s,tpenv
else
let aty = NewInferenceType ()
let bty = NewInferenceType ()
let cty = NewInferenceType ()
let dty = NewInferenceType ()
let ety = NewInferenceType ()
let ty' = mkPrintfFormatTy cenv.g aty bty cty dty ety
if (not (isObjTy cenv.g overallTy) && AddCxTypeMustSubsumeTypeUndoIfFailed env.DisplayEnv cenv.css m overallTy ty') then
// Parse the format string to work out the phantom types
let aty',ety' = (try Formats.ParseFormatString m cenv.g s bty cty dty with Failure s -> error (Error(FSComp.SR.tcUnableToParseFormatString(s),m)))
UnifyTypes cenv env m aty aty';
UnifyTypes cenv env m ety ety';
mkCallNewFormat cenv.g m aty bty cty dty ety (mkString cenv.g m s),tpenv
else
UnifyTypes cenv env m overallTy cenv.g.string_ty;
mkString cenv.g m s,tpenv

这是同样的代码,它也支持数字字符串(即 printfn "%i %i"("4"+ 2) "5" 将类型检查并打印 6 5):

and TcConstStringExpr cenv overallTy env m tpenv s  =

if (AddCxTypeEqualsTypeUndoIfFailed env.DisplayEnv cenv.css m overallTy cenv.g.string_ty) then
mkString cenv.g m s,tpenv
elif (AddCxTypeEqualsTypeUndoIfFailed env.DisplayEnv cenv.css m overallTy cenv.g.int_ty) then
mkInt cenv.g m (System.Int32.Parse s),tpenv
elif (AddCxTypeEqualsTypeUndoIfFailed env.DisplayEnv cenv.css m overallTy cenv.g.int32_ty) then
mkInt32 cenv.g m (System.Int32.Parse s),tpenv
else
let aty = NewInferenceType ()
let bty = NewInferenceType ()
let cty = NewInferenceType ()
let dty = NewInferenceType ()
let ety = NewInferenceType ()
let ty' = mkPrintfFormatTy cenv.g aty bty cty dty ety
if (not (isObjTy cenv.g overallTy) && AddCxTypeMustSubsumeTypeUndoIfFailed env.DisplayEnv cenv.css m overallTy ty') then
// Parse the format string to work out the phantom types
let aty',ety' = (try Formats.ParseFormatString m cenv.g s bty cty dty with Failure s -> error (Error(FSComp.SR.tcUnableToParseFormatString(s),m)))
UnifyTypes cenv env m aty aty';
UnifyTypes cenv env m ety ety';
mkCallNewFormat cenv.g m aty bty cty dty ety (mkString cenv.g m s),tpenv
else
UnifyTypes cenv env m overallTy cenv.g.string_ty;
mkString cenv.g m s,tpenv

P.S.:我很久以前写过这个,所以我不记得为什么那里有 mkIntmkInt32 。这可能是必要的,也可能不是 - 但我确实记得这段代码有效。

关于.net - F# printf 编译器魔法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17109262/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com