Julia: API一致性检查

创建于 2017-02-02  ·  131评论  ·  资料来源: JuliaLang/julia

我将从这里开始留下一些注意事项,以确保在Julia 1.0中检查API一致性时要加以考虑。

  • [x]公约优先次序。 根据功能块的功能参数,打印功能的IO参数,就地功能的输出等列出和优先考虑我们的What-c​​omes-first约定(https://github.com/JuliaLang/julia/issues/ 19150)。

  • []位置vs关键字参数。 很久以前,我们没有关键字参数。 出于性能考虑,有时仍会避免使用它们。 我们应该基于使API最佳的方式做出选择,而不是基于那种历史包((也应该解决关键字性能问题,这样就不再考虑了)。

  • []元编程工具。 我们有很多工具,例如@code_xxx和诸如code_xxx类的基础功能配对。 它们应该表现一致:相似的签名,如果存在具有相似签名的函数,请确保它们具有相似的宏版本。 理想情况下,它们应该全部返回值,而不是某些返回值和其他打印结果,尽管对于LLVM代码和汇编代码而言可能很难。

  • [] IO <=>文件名等效。 我们通常允许将文件名作为字符串传递来代替IO对象,并且标准行为是以适当的方式打开文件,将产生的IO对象传递给具有相同参数的相同函数,然后确保IO对象之后关闭。 验证所有适当的IO接受功能都遵循此模式。

  • [] Reducers API。 确保减速器具有一致的行为–所有减速器都具有映射功能,然后进行减速; 一致的维度参数等

  • []尺寸参数。 一致对待“在此维度上进行计算”输入参数,允许使用的类型等,请考虑是否需要将它们作为关键字args使用。

  • []变异/非变异对。 检查非突变函数是否与有意义的突变函数配对,反之亦然。

  • []元组与vararg。 检查函数是否将元组作为最后一个参数或将变量作为参数,是否存在一般一致性。

  • []联合与可为空与错误。 关于何时函数应引发错误以及何时应返回Nullable或并集(例如,解析/ tryparse,match等)的一致规则。

  • []尽可能广泛地支持生成器。 确保可以合理地与生成器一起使用的任何功能都可以这样做。 我们已经对此做得很好,但是我想我们已经错过了一些。

  • []输出类型选择。 关于“输出类型” API应该是元素类型还是整体容器类型(参考#11557和#16740)应保持一致。

  • [x]选择一个名字。 有一些具有别名的功能/运算符。 我觉得这是好的在情况下,名称中的一个非ASCII和ASCII版本提供了这样的人仍然可以写纯ASCII码,但也有类似的情况<:这是一个别名issubtype ,其中两个名称均为ASCII。 我们应该选择一个,然后弃用另一个。 我们不建议使用is ,而建议使用===并且在这里也应这样做。

  • []DataStructures的一致性。 它在某种程度上超出了Base Julia的范围,但是我们应该确保DataStructures中的所有集合都具有与Base提供的一致的API。 另一个方面的联系是,其中某些类型可能会告诉我们最终如何在Base中设计API,因为我们希望它们平稳且一致地扩展。

  • [] NaN与DomainErrors。 参见https://github.com/JuliaLang/julia/issues/5234 –制定何时执行操作的政策,并确保始终遵循。

  • []集合<=>生成器。 有时您需要一个集合,有时您需要一个生成器。 我们应该遍历所有API,并确保在可行的情况下都针对这两个选项进行选择。 很久以前,就有一种约定,对于生成器版本,使用大写名称,对于急切的并返回新集合的版本,使用小写名称。 但是没有人对此给予任何关注,所以也许我们需要一项新的约定。

  • []关联函数的高阶函数。 当前,一些高阶函数遍历具有签名(k,v)关联集合,例如mapfilter 。 其他人则在对上进行迭代,即使用签名kv ,要求主体将对显式地分解为kv –例如allany 。 应该对此进行审查并使其一致。

  • [x]转换与构造。 在适当的地方允许转换。 例如,关于convert(String, 'x')存在多个问题。 通常,只有一个规范转换时才适合使用转换。 通常,将字符串转换为数字是不合适的,因为有很多文本方式可以表示数字,因此我们需要使用选项来解析。 但是,有一种规范的方式可以将版本号表示为字符串,因此我们可以将其转换。 我们应该谨慎,普遍地运用这种逻辑。

  • []查看collections API的完整性。 我们应该查看其他语言提供的集合的标准库函数,并确保我们有一种表达它们所具有的常用操作的方式。 例如,我们没有flatten函数或concat函数。 我们可能应该。

  • []强调审核。

deprecation

最有用的评论

下划线审核

以下是对从Base导出的所有符号的分析,这些符号包含下划线,不推荐使用且也不是字符串宏。 这里要注意的主要是,这些仅是导出的名称。 这不包括我们告诉人们称呼合格的未导出名称。

我已按类别将事物分开。 希望这比烦人的事有用。

反射

我们具有以下具有相应功能的宏:

  • [] @code_llvmcode_llvm
  • [] @code_loweredcode_lowered
  • [] @code_nativecode_native
  • [] @code_typedcode_typed
  • [] @code_warntypecode_warntype

无论对宏进行的任何更改(如有),都应类似地应用于函数。

  • [x] module_name -> nameof (#25622)
  • [x] module_parent -> parentmodule (#25629,请参阅#25436以获取先前的重命名尝试)
  • [x] method_exists -> hasmethod (#25615)
  • [x] object_id -> objectid (#25615)
  • [] pointer_from_objref

pointer_from_objref也许可以使用更具描述性的名称,例如address

C互操作别名

包含下划线的类型别名为C_NULLCintmax_tCptrdiff_tCsize_tCssize_tCuintmax_tCwchar_t 。 那些以_t结尾的代码应该保留,因为它们被命名为与其对应的C类型一致。

C_NULL在这里很奇怪,它是唯一的C别名包含一个未在C中镜像的下划线(因为在C中,这只是NULL )。 我们可以考虑将其称为CNULL

  • [] C_NULL

位计数

  • [] count_ones
  • [] count_zeros
  • [] trailing_ones
  • [] trailing_zeros
  • [] leading_ones
  • [] leading_zeros

有关重命名这些标签的讨论,请参见#23531。 我非常赞成删除这些下划线以及该PR中的一些建议替代内容。 我认为应该重新考虑。

不安全的操作

  • [] unsafe_copyto!
  • [] unsafe_load
  • [] unsafe_pointer_to_objref
  • [] unsafe_read
  • [] unsafe_store!
  • [] unsafe_string
  • [] unsafe_trunc
  • [] unsafe_wrap
  • [] unsafe_write

保持这些原样可能还可以; 下划线的丑陋进一步强调了它们的不安全性。

索引编制

  • [] broadcast_getindex
  • [] broadcast_setindex!
  • [] to_indices

显然存在broadcast_getindexbroadcast_setindex! 。 我不明白他们在做什么。 也许他们可以使用更具描述性的名称?

有趣的是,未导出to_indicesBase.to_index的单索引版本。

痕迹

  • [] catch_backtrace
  • [x] catch_stacktrace -> stacktrace(catch_backtrace()) (#25615)

假设这些分别是等效于backtracestacktracecatch块等效项。

任务,流程和信号

  • [] current_task
  • [] task_local_storage
  • [] disable_sigint
  • [] reenable_sigint
  • [] process_exited
  • [] process_running

  • [] redirect_stderr
  • [] redirect_stdin
  • [] redirect_stdout
  • [x] nb_available -> bytesavailable (#25634)

最好有一个更通用的IO -> IO重定向函数,可以将所有这些重定向函数合并在一起,例如redirect(STDOUT, io) ,从而删除下划线和导出。

晋升

  • [] promote_rule
  • [] promote_shape
  • [] promote_type

有关promote_rule的相关讨论,请参见#23999。

列印

  • [x] print_with_color -> printstyled (请参阅#25522)
  • [] print_shortest (请参阅#25745)
  • [] escape_string (请参阅#25620)
  • [] unescape_string

escape_stringunescape_string有点奇怪,因为它们可以打印到流或返回字符串。 有关移动/重命名这些建议的信息,请参见#25620。

代码加载

  • [] include_dependency
  • [] include_string

include_dependency 。 这甚至在Base之外使用吗? 我想不出在任何典型情况下都希望用它代替include情况。

include_string 。 这不只是eval(parse())的官方认可版本吗?

我没有打扰的事情

  • [x] gc_enable -> GC.enable (#25616)
  • [] get_zero_subnormals
  • [] set_zero_subnormals
  • [] time_ns

get_zero_subnormalsset_zero_subnormals可以使用更具描述性的名称。 他们需要出口吗?

所有131条评论

抱歉,如果这不是合适的地方,但是最好与以后的函数名中的下划线保持一致。

不,这是个好地方。 是的,我们应该努力消除所有需要下划线的名称:)

  • 对“在此[这些]维度上计算”输入参数的一致处理,允许的类型等,请考虑是否需要将它们作为关键字args使用
  • 根据功能块的功能参数,打印功能的IO参数,就地功能的输出等列出并区分优先顺序

对于@tkelman的第二点,请参阅https://github.com/JuliaLang/julia/issues/19150

最近还有关于find的API和相关功能的Julep: https :

因为我们有push!shift! ,我们是否应该在渠道上弃用put!take! (对于期货也可以这样做)? 只是建议在API中删除2个多余的单词。

我怀疑shift!是用户友好的。 候选人为fetch!我们已经有fetch ,这是take!的不变版本

编号#13538#12469

@amitmurthy @malmaud

编辑:在频道上重用sendrecv甚至更有意义。 (我很惊讶,目前这些仅用于UDPSockets)

+1,将put! / take!替换push! / fetch!

我将重命名@inferred@test_inferred

仔细检查专业化是否与更通用的功能一致,即与#20233不同。

查看所有导出的函数,以检查是否可以通过将其替换为多个调度来消除它们,例如,print_with_color

使用类似队列的数据结构时,典型的配对是push!shift!

如果我们不担心将典型的名称配对用于这种数据结构,因为我们担心该操作会带来通信费用,而这些名称不能充分传达这些费用,那么我认为push!也有意义。 sendrecv可能更好。

也许要仔细检查一下函数是否将元组作为最后一个参数或将变量作为参数之间存在总体一致性。

也许对于这个问题来说太大了,但是对于何时应该引发错误以及何时应该返回Nullable s或Union s(例如parse / tryparsematch等)

没问题, @ simonbyrne –这是洗衣清单。

顺便说一句:这实际上不是针对特定的更改(例如,重命名特定的功能)–而是我们可以审查的各种事情。 对于建议的特定更改,只需打开一个提出更改的问题。

我们有很多工具,例如@code_xxx和基础代码(例如code_xxx)配对

不知道这是您在说什么,但请参阅CreateMacrosFrom.jl

  • “输出类型” API应当是元素类型还是整体容器类型(参考#11557和#16740)
  • 记录所有导出的功能(包括doctest)

记录所有导出的功能(包括doctest)

如果这是其中的一部分,那么也许还:请记住用问题/公关编号标记您的测试。 这使人们更容易理解为什么要进行该测试。 我知道git怪是怎么工作的,但是在添加测试集时(仅举一个例子),有时要测试的东西有点神秘,如果问题/公关号始终存在,那就太好了。

@dpsanders :和导出的宏! 例如@fastmath没有文档字符串。

这是非常小的,但是stringSymbol函数的作用几乎相同,但大小写不同。 我认为symbol会更有意义。

@amellnik的区别在于Symbol是类型构造函数,而string是常规函数。 IIRC我们曾经有symbol但由于类型构造函数而被弃用。 我不认为需要对此进行更改,但是我认为如果有任何更改,我们应该使用String构造函数代替string

如果有的话,我认为我们应该使用String构造函数代替string。

不,它们是不同的功能,不应合并

julia> String(UInt8[])
""

julia> string(UInt8[])
"UInt8[]"

不,它们是不同的功能,不应合并

这看起来像这样一种情况,其中只应弃用string(args...) ,而赞成sprint(print, args...) ,然后-同时拥有stringString会造成混淆。 我们可以专注于sprint(::typeof(print), args...)来恢复任何丢失的性能。 按照这些思路,将repr(x)弃用为sprint(showall, args...)也是有意义的。

听起来不错,尽管调用string将东西变成字符串似乎很标准...。

调用字符串将某些东西变成字符串似乎很标准

是的,但这就是Stringstring之间断开连接的地方。

sprint(print, ...)感到多余。 如果我们摆脱了string ,我们可以将sprint重命名string这样我们得到string(print, foo)string(showall, foo)在我看来很好。

这可能是一致性被高估的情况。 我认为将string(x)用于“只给我x的字符串表示形式”就可以了。 如果要比这更复杂,例如要求您指定要使用的打印功能,则可以使用sprint类的其他名称。

我也可以将String(UInt8[])重命名String代替stringstring使我们将来可以更灵活地更改返回的字符串类型,但这似乎不太可能发生。

reinterpret(String, ::Vector{UInt8}是否完全有意义,或者这是reinterpret的双关语?

这似乎是有道理的。

问题是该函数有时会被复制,因此名称有些误导。

没错,但是字符串应该是不可变的,因此我们可以避免它。

还有一个String(::IOBuffer)方法,但似乎可以将其弃用为readstring

我也考虑过您提出的API更改,但是string(a, b...)的接口是它将其参数字符串化和连接起来,这将使可调用的第一个参数成为一个烦人的陷阱。 如果我们从string删除串联,则可以使其起作用。

是的,同意; 一致性和避免陷阱最重要。

注意“维度参数”类别中的问题#18326和#3893。

如果我可以提出另一个建议:请确保可变容器的行为已记录在案并保持一致。

@ JaredCrean2 :您能详细说明一下这是什么意思吗?

我当然希望它不会涉及制作很多“防御性副本”。

例如,如果我有一个可变类型的数组,并在其上调用sort ,则返回的数组指向与输入数组相同的对象,还是复制对象并使返回的数组指向他们?

相同的对象。 我很确定我们所有的集合排序,获取索引,过滤,搜索等方法都遵循此规则,不是吗?

我认为在这一点上没有任何缺乏明确性或一致性的地方–它始终是相同的对象。

实际上,我认为不是这种情况的唯一标准函数是deepcopy ,其关键是要获取所有新对象。

那是记录在某处吗?

不,我们可以,但是我不确定最好在哪里进行记录。 为什么函数会不必要地复制? 您从哪里得到他们可能会留下的印象?

你好。 我还没有看到我相信有关数据序列化的任何言论。

不久或将来,朱莉娅程序将被编写并公开运行,多年来,数据有时会开始分层。 数据序列化 chain:必须根据时间类型来构造对象(由json或...来驱动)所指向的字节。 关于语义版本控制和Web API的思考也很重要。

我们是否可以期望用户数据的序列化保持在https://github.com/JuliaLang/julia/blob/v0.5.1/base/serialize.jl附近?

为什么函数会不必要地复制? 您从哪里得到他们可能会留下的印象?

我不知道他们是否这样做。 据我所知,该行为是不确定的。 从@JeffBezanson的评论中,有些人主张制作防御性副本,他反对。 因此,文档应在某处解决防御性副本的问题。

您似乎在暗示某种最小动作原理,但是根据算法的细节,什么是“最小动作”变得模棱两可。 为了使API保持一致,我认为需要更具体的指导。

@ o314 :这是一个API一致性审查问题,我不确定序列化之间的关系。

@ JaredCrean2 :是否必须复制顶级对象是否被复制。 我的意思是,除非通过Deepcopy(显然),否则永远不会复制更深层的对象。

我的意思是,除非通过Deepcopy(显然),否则永远不会复制更深层的对象。

最近在一些数组包装的copy上下文中对此进行了讨论,例如SubArraySparseMatrixCSC以及SymmetricLowerTriangular 。 在我看来,根据上述政策, copy对于此类包装器类型将是无济于事的。 您在这里提到的策略是正确的抽象级别吗? 例如,我认为这意味着如果Array s是在Julia中实现的(包装缓冲区),则copyArray的行为应更改为noop。

如果约定是永远不要复制更深的对象,那么剩下的就是记录它。 文档是API的重要组成部分。 这种行为对您来说似乎很明显(也许是因为您编写了代码的一部分),但是从外部角度来看,它并不是那么明显。

编辑:没有看到安德里亚斯的帖子。 这是一个有趣的考虑。

@StefanKarpinski我同意你的观点。
而且这里讲到的所有主要主题都非常好,很聪明。

但是我有时会担心在Julia中流程和数据之间的平衡:

我们可以肯定地轻松调用fortran或c,
但是,例如,将代码轻松部署在现代数据中心上。 aws lambda及其功能,作为服务模式。 通过api,开放api可以轻松调用代码吗?

有时,人们必须降低功能负载以进行扩展(没有泛型,在函数签名上没有vaargs,在公共api上没有高阶),并且在后面绑定了更系统的数据(json模式/ openapi)。

我已经看到一些很好的python库以这种方式下沉,这很可惜。

我认为,对于语言1.0来说,保持数据和功能的平衡以及模块化以便能够轻松地在Web上进行部署是至关重要的。 对于此功能接口,在需要时必须减少宠物的使用,而应更加注重牛。

可能这不是本主题的重点。

@StefanKarpinski我可能误解了您的帖子。 当你说

是否复制顶级对象肯定需要记录在案

“顶级对象”是什么意思? 如果我有x::Vector{MyMutableType} ,是顶级对象x还是x的元素?

顶级对象是指x本身,而不是x的元素。

@andreasnoack顶级对象的概念应引用已实现的抽象结构,而不是实现细节。

也许添加float和其他对类型和值都起作用的类似函数?

在0.6发行说明上,引入iszero(A::Array{T})似乎很奇怪,而数组上的许多其他函数(例如sumabsisintegerisnumber )却是不推荐使用all(f,A)

数组为零,向量空间为零。 iszero通常测试某些东西是否是加法逆,即零数组是什么。

回覆。 函数名称中下划线的一致性,这是count_onescount_zeros的面包屑。

在我看来,如果要保持Julia API始终如一的一致性,则需要安装一些软件,以便您(a)指定API规则/约定是什么,(b)对Julia代码执行静态分析以检测与这些规则/惯例的背离,以及(c)提供建议。 这样的工具将使Julia Base和所有Julia Packages受益。 一个新的Julia包可能会解决问题。 (面颊上的舌头:这个包应该做的第一件事就是建议自己的名字; APICheck.jl,ApiCheck.jl,API_Check.jl,APIChecker.jl,JuliaAPIChecker.jl等)。所以不想牵头这样的事情。 但是,我不介意做出贡献。 有关如何进行此操作的任何建议?

我们希望在Lint.jl中拥有它!

num2hexhex2num (#22031和#22088)

我也相信Lint.jl是用于Julia API一致性检查的正确软件包。 但是,如果我们走这条路,那么斯特凡的原始名单必须做得更加精确。 例如,当他写“我们应该确保DataStructures中的所有集合都具有一致的API”时,想到的问题是:

  • 是什么使数据结构成为集合? (基础集合列表)
  • 集合必须支持哪些功能? (按集合的功能电子表格)
  • 每个功能的签名应该是什么?
  • Base为集合提供的API是否实际上已经一致?

为了管理这样的清单和分析,我们可能想要将项目添加到Julia储存库(项目8),或添加到JuliaPraxis储存库(由TotalVerb建议脱机)或Lint储存库。 在那种情况下,我们需要挑选出谁将拥有这样一个项目,从一开始就应该让哪些人参与,以及谁应该就Julia公约的实际含义做出最终决定(以利弊为目的)。

但是,在按照这些方式进行进一步介绍之前,我想问一问@StefanKarpinski :您对处理Julia API一致性问题列表有何想法?

我同意明确指出这是一个好主意。 弄清楚该列表应该是此处工作的一部分–如果您想对其进行破解,那就太好了。

我们真的需要一个Base.datatype_module和一个Base.function_module吗?

对数据类型和函数进行调度的统一函数“模块”(也许是getmodule)对我来说似乎更一致。

那么@code_typed和朋友中的下划线呢?

这是一个很好的重构机会(下划线禁止的陈述原因)。 您可能有一个@code宏,第一个参数是您想要的代码类型。

@bramtayl ,请记住要在宏周围加上反引号,因为这会ping github用户“ code”; @code

FWIW,制表符补全仅适用于函数名称。 能够做@code_<TAB>很不错....

如果考虑重构但拒绝重构,那么是否存在下划线是没有意义的,因为下划线禁止的唯一目的是鼓励重构。 实际上,在这种情况下,似乎应该鼓励使用下划线来使语言更清晰

强调审核。

反对建议:我们仍然审核这些名称,但是我们在代码下添加了更多的下划线,以使代码更易于阅读(codetyped与code_typed,isos2与is_os2)。

我不是绝对主义者。 我认为code_typed很好,如@KristofferC所指出的那样,制表符

在我看来,这艘船似乎在航行中增加了更多的下划线,因为我们不得不基本弃用Base的一半。 例如,有74个谓词函数以is开头,只有6个谓词函数以is_开头。 弃用6或74,哪个更有意义?

好的,这里有几个相互冲突的目标:

1)使名称更具可读性
2)减少代码流失
3)鼓励重构

在三个方面都无法通过将单词相互碰撞来消除下划线。

接受流的show方法不是!终止的,这似乎与通常的约定不一致吗? 参考 https://github.com/JuliaLang/julia/pull/22604/commits/db9d70a279763ded5088016d9c3d4439a49e3fca#r125115063。 最好! (编辑:我想这与接受流的write方法匹配。)

与traits API不一致。 一些特征是通过调用特征来计算的,例如
TypeArithmetic(Float64)
而其他函数则必须拼写为小写:
iteratorsize(Vector{Float64})

考虑重命名size -> shape (外部参照#22665)

Array{T,1}()应该被弃用:

julia> Array{Int,1}()                                                                                                                  
0-element Array{Int64,1}                                                                                                               

julia> Array{Int,2}()                                                                                                                  
WARNING: Matrix{T}() is deprecated, use Matrix{T}(0, 0) instead.                                                                       

一直在考虑收藏。 我们基本上有三种:

  • 简单的集合式(或袋式)集合,其中仅包含一些值。
  • 类似于数组的集合,可在数据旁边添加索引。
  • 类似Dict的集合,其索引作为数据的一部分,即k=>v对。

我对类似dict的行为表示怀疑。 煤矿中的金丝雀是map ,其中对键值对进行操作是不自然的,因为您通常不想更改键集。 数组和字典也可以实现相同的接口:

  • keys对应于eachindex
  • mapindexedfilterindexed对字典和数组都有用。 这些就像地图和过滤器,除了还可以通过您的函数将有关项目的索引。
  • 数组和字典(并命名为元组,也许还有其他东西)可以使用pairs迭代器,这基本上是zip(keys(c), values(c))的快捷方式。

考虑重命名ind2subsub2ind ,这显然是matlabisms,对于非matlab用户,它们具有非朱利安语和奇怪的名字。 可能的名称分别是indicelinearindice 。 我不敢做公关,因为我不确定人们对此有何看法,但是如果有支持,我会做。

rad2degdeg2rad

参考 #22791( select -> partialsort )。 最好!

我没有在这里看到的一件事:可选的位置参数排在最前面还是最后? 有时,可选的位置参数排在第一位,例如sum(f, itr)rand([rng,] ..) 。 但在其他地方,它们排在最后,例如median(v[, region])split(s::AbstractString[, chars]) 。 有时他们可以先走,也可以走最后,但不能两者都走! (例如, mean可以首先使用一个函数,或者最后采用一个维,但不能同时使用两者。)

当前的语言语义迫使可选参数排在最后:您可以编写f(a, b=1)但不能编写f(b=1, a) 。 但是,如果所有可选参数都排在最后,那么方便的块会发生什么?

如果没有其他要求,那么该语言必须从rand.jlshuffle!(a::AbstractVector) = shuffle!(GLOBAL_RNG, a)定义这样的方法,这是一个小小的错误。 可选的位置参数语法应恰好处理此用例。

也许应该在一个单独的问题中解决,但似乎可以将可选参数移到所需的位置。 因此,例如, f(a = 1, b, c = 2)将定义f(x) = f(1, x, 2)f(x, y) = f(x, y, 2)

外部参照#22460,尝试(不受欢迎)尝试在任何位置启用默认args。

也许将warn重命名warning (matlab也使用此名称),没什么大不了的,但是我想提一提?

我喜欢warn因为它是动词,例如throw

我对此感到非常困惑:

julia> f(;a=1,b=1) = a+b                                                                                                                              
f (generic function with 1 method)                                                                                                                    

julia> f(a=4,5)            # I intended to write f(a=4,b=5)                                                                                                                           
ERROR: MethodError: no method matching f(::Int64; a=4)                                                                                                
Closest candidates are:
  f(; a, b) at REPL[13]:1

我建议在调用函数时仅允许关键字最后使用,类似于定义关键字函数时。

我建议在调用函数时仅允许关键字最后使用,类似于定义关键字函数时。

在许多API中,在其他位置传递关键字既有用又符合人体工程学。

出于好奇,是否为位置和关键字参数确定了评估顺序? 我看到了一些较旧的问题,并且https://docs.julialang.org/en/latest/manual/functions/#Evaluation -Scope-of-Default-Values-1讨论了范围,但是我没有发现任何状态,例如从左到右评估参数,或者在所有关键字参数之前评估所有位置参数,或者如果没有定义的评估顺序(或其他)。

@yurivish ,有关关键字,请参阅文档(另请参见https://github.com/JuliaLang/julia/issues/23926)。 对于可选的故事,故事要复杂一些,也许可以在这里阅读。 (请注意,虽然最好在https://discourse.julialang.org/上提问)

似乎不值得这样做,但让我总是感到奇怪的是bits(1)返回String ,似乎应该是BitVectorVector{Bool}

我想建议回顾一下FunctionCallable上调度的方法表。 让我们尝试确保这些API就是我们想要的方式……并且我们没有错过任何机会来重组表,以便我们可以允许鸭子调用任何对象。

至于allany ,它们似乎很容易折旧为all(f(x) for x in xs) ,它已经被eta简化为all(Generator(f, xs)) ,因此应该没有开销。

不知道这是你的意思,但我想它的价值陈述,以防万一:我反对贬低任何功能性风格的API发电机铁杆。 我们有any(f, x)all(f, x) ,它们被广泛使用; -10000000以删除这些(或其他任何此类方法)。

我是专业发电机。 似乎是惰性编程的基本构建块,应该将其导出。 all(Generator(f, xs))有时比all(f(x) for x in xs)对定义的函数更方便。 还+10000000恢复余额

如果可能的话,我希望这里的语法更少。 如果表达“采取xs,将f应用于所有事物,并在所有这些都是正确的情况下返回true”的想法很容易理解并且表现出色,那么为什么要将它放在一个动词中?

如果关注的是f(x) for x in xs不必要的名词x ,则@bramtayl建议导出Generator (也许使用更好的名称,例如Map ?)说得通。

all(isnull, x)这样的东西比all(isnull(v) for v in x)要简单得多。 我们从NullableArrays中弃用了allnull函数,而推荐使用all(isnull, x) ; 如果该语法消失了,我们可能必须重新引入它。

如何将strwidth重命名stringwidth (我认为这是唯一将字符串缩写为str的导出字符串操作函数)

实际上,它已被重命名为textwidth (https://github.com/JuliaLang/julia/pull/23667)。

IMO,鉴于我们希望尽快冻结功能,因此此问题过于广泛,无法拥有1.0里程碑。 如果要执行此操作,我们可能需要多个所有者并分配功能集进行审查。

另外,这是FemtoCleaner可以在1.0之后自动更新许多内容的另一个地方,即使将其正确处理也很不错。

只是对textwidth的评论:

INFO: Testing Cairo
Test Summary:   | Pass  Total
Image Surface   |    7      7
Test Summary:   | Pass  Total
Conversions     |    4      4
Test Summary:   | Pass  Total
TexLexer        |    1      1
WARNING: both Compat and Cairo export "textwidth"; uses of it in module Main must be qualified
Samples        : Error During Test
  Got an exception of type LoadError outside of a <strong i="6">@test</strong>
  LoadError: UndefVarError: textwidth not defined
  Stacktrace:
   [1] include_from_node1(::String) at .\loading.jl:576
   [2] include(::String) at .\sysimg.jl:14
   [3] macro expansion at C:\Users\appveyor\.julia\v0.6\Cairo\test\runtests.jl:86 [inlined]
   [4] macro expansion at .\test.jl:860 [inlined]
   [5] anonymous at .\<missing>:?
   [6] include_from_node1(::String) at .\loading.jl:576
   [7] include(::String) at .\sysimg.jl:14
   [8] process_options(::Base.JLOptions) at .\client.jl:305
   [9] _start() at .\client.jl:371
  while loading C:\Users\appveyor\.julia\v0.6\Cairo\samples\sample_pango_text.jl, in expression starting on line 28

该错误消息似乎很清楚是什么问题? Cairo需要扩展基本方法。

help?>  Base.textwidth
  No documentation found.

  Binding Base.textwidth does not exist.

julia> versioninfo()
Julia Version 0.6.0
julia> Compat.textwidth
textwidth (generic function with 2 methods)

我毫不怀疑消息(通过travis获得)是可以的,但是如果Compat不在0.6中,为什么Compat会导出textwidth?

因为那是Compat的重点? 尽管此讨论的范围很广,所以我建议我们可以继续进行讨论或放松讨论。

我建议将copy更改shallowcopy ,将deepcopy更改copy ,因为最近我花了很多时间才意识到副本是“浅”副本,并且我写的函数是改变数组的数组,我想如果copy做一个“深层”副本,而像shallowcopy的浅层副本会更直观呢?什么时候使用deepcopy ,但是我认为许多其他用户也会遇到相同的问题。

为了保持API的一致性,请尝试保持此问题,而不是“我不喜欢的特定内容”。

Associative的名字似乎与所有在朱莉娅的其他类型的名字不一致。

首先,类型通常不是形容词。 名词是Association ,至少我发现的一些Mathematica文档使用了该名词。

我认为, AbstractDict极大地与其他类型,如比较一致的AbstractArrayAbstractRangeAbstractSetAbstractString ,每个都有典型的具体类型DictArrayRangeSetString

我们的异常类型到处都是:有些命名为FooError ,有些命名为BarException ; 一些出口,大多数没有。 这可以使用传递来保持一致性。

那么,首选FooErrorBarException吗? 是否出口?

对我来说, BarException涉及某种提升/捕捉模式。

我更喜欢,在功能世界中,还有一些人也使用Some / None模式(*),其中控制流更直接,更可预测。

所以+1为FooError

(*) Some / Void不含Optional的茱莉亚#23642。

考虑到功能冻结,这些东西还在桌上吗? 我特别想解决可选参数与关键字参数的问题,但是具有多个可选参数的函数列表(最明显的情况是使用关键字参数)。

请看一下! 我没有机会系统地解决这些问题。

顺便说一句,我注意到特征的命名不一致:我们有iteratorsizeiteratoreltype ,但是IndexStyleTypeRangeStepTypeArithmeticTypeOrder 。 看起来CamelCase变体越来越多,越来越新,所以也许我们应该在所有地方都采用该约定?

这些绝对应该保持一致。 你想做公关吗?

我认为这应该作为https://github.com/JuliaLang/julia/pull/25356的一部分进行修复

编辑:另请参阅https://github.com/JuliaLang/julia/issues/25440

这主要是完成的,或者可以在1.x版本中完成。 我可以更新复选框,但我们只是在分流调用中对它们进行了检查,除#25395和下划线审核之外的所有内容均已完成。

下划线审核

以下是对从Base导出的所有符号的分析,这些符号包含下划线,不推荐使用且也不是字符串宏。 这里要注意的主要是,这些仅是导出的名称。 这不包括我们告诉人们称呼合格的未导出名称。

我已按类别将事物分开。 希望这比烦人的事有用。

反射

我们具有以下具有相应功能的宏:

  • [] @code_llvmcode_llvm
  • [] @code_loweredcode_lowered
  • [] @code_nativecode_native
  • [] @code_typedcode_typed
  • [] @code_warntypecode_warntype

无论对宏进行的任何更改(如有),都应类似地应用于函数。

  • [x] module_name -> nameof (#25622)
  • [x] module_parent -> parentmodule (#25629,请参阅#25436以获取先前的重命名尝试)
  • [x] method_exists -> hasmethod (#25615)
  • [x] object_id -> objectid (#25615)
  • [] pointer_from_objref

pointer_from_objref也许可以使用更具描述性的名称,例如address

C互操作别名

包含下划线的类型别名为C_NULLCintmax_tCptrdiff_tCsize_tCssize_tCuintmax_tCwchar_t 。 那些以_t结尾的代码应该保留,因为它们被命名为与其对应的C类型一致。

C_NULL在这里很奇怪,它是唯一的C别名包含一个未在C中镜像的下划线(因为在C中,这只是NULL )。 我们可以考虑将其称为CNULL

  • [] C_NULL

位计数

  • [] count_ones
  • [] count_zeros
  • [] trailing_ones
  • [] trailing_zeros
  • [] leading_ones
  • [] leading_zeros

有关重命名这些标签的讨论,请参见#23531。 我非常赞成删除这些下划线以及该PR中的一些建议替代内容。 我认为应该重新考虑。

不安全的操作

  • [] unsafe_copyto!
  • [] unsafe_load
  • [] unsafe_pointer_to_objref
  • [] unsafe_read
  • [] unsafe_store!
  • [] unsafe_string
  • [] unsafe_trunc
  • [] unsafe_wrap
  • [] unsafe_write

保持这些原样可能还可以; 下划线的丑陋进一步强调了它们的不安全性。

索引编制

  • [] broadcast_getindex
  • [] broadcast_setindex!
  • [] to_indices

显然存在broadcast_getindexbroadcast_setindex! 。 我不明白他们在做什么。 也许他们可以使用更具描述性的名称?

有趣的是,未导出to_indicesBase.to_index的单索引版本。

痕迹

  • [] catch_backtrace
  • [x] catch_stacktrace -> stacktrace(catch_backtrace()) (#25615)

假设这些分别是等效于backtracestacktracecatch块等效项。

任务,流程和信号

  • [] current_task
  • [] task_local_storage
  • [] disable_sigint
  • [] reenable_sigint
  • [] process_exited
  • [] process_running

  • [] redirect_stderr
  • [] redirect_stdin
  • [] redirect_stdout
  • [x] nb_available -> bytesavailable (#25634)

最好有一个更通用的IO -> IO重定向函数,可以将所有这些重定向函数合并在一起,例如redirect(STDOUT, io) ,从而删除下划线和导出。

晋升

  • [] promote_rule
  • [] promote_shape
  • [] promote_type

有关promote_rule的相关讨论,请参见#23999。

列印

  • [x] print_with_color -> printstyled (请参阅#25522)
  • [] print_shortest (请参阅#25745)
  • [] escape_string (请参阅#25620)
  • [] unescape_string

escape_stringunescape_string有点奇怪,因为它们可以打印到流或返回字符串。 有关移动/重命名这些建议的信息,请参见#25620。

代码加载

  • [] include_dependency
  • [] include_string

include_dependency 。 这甚至在Base之外使用吗? 我想不出在任何典型情况下都希望用它代替include情况。

include_string 。 这不只是eval(parse())的官方认可版本吗?

我没有打扰的事情

  • [x] gc_enable -> GC.enable (#25616)
  • [] get_zero_subnormals
  • [] set_zero_subnormals
  • [] time_ns

get_zero_subnormalsset_zero_subnormals可以使用更具描述性的名称。 他们需要出口吗?

method_exists => methodexistsobject_id => objectid +1。 catch_stacktrace甚至存在也很愚蠢。 可以弃用它的定义stacktrace(catch_backtrace())

我们对取消强调C_NULL感觉如何? 我已经习惯了,但是我也赞成这样一种说法,即其他C*名称都没有下划线。

其他C名称是类型,而C_NULL是常数。 我认为这是很好的,并且遵循命名准则。

并遵循命名准则。

为何如此?

常量通常都是带下划线的大写字母,其后是C_NULL 。 正如@ iamed2所说,它是一个值,而不是类型,因此Cfoo命名约定不一定适用。

我误以为https://github.com/JuliaLang/julia/blob/master/doc/src/manual/variables.md#stylistic-常规引用了常量,但事实并非如此。 它可能应该。

对于一般的希尔伯特空间(其中矢量不是Julia数组),我建议一个在数学上一致的接口。 像vecdotvecnorm等之类的函数名很可能会被替换为innernorm的一般概念,如https:// github上所述。 com / JuliaLang / julia / issues / 25565。

正如我已经说过几次,对于要更改的事情来说,这不是一个总的问题。

我相信在此伞下仅剩余的1.0项是#25501和#25717。

我想用(get|set)_zero_subnormals做点什么,但是最好的短期解决方案是只取消导出它们。

应该回顾一下在mapcollect类的集合操作中如何处理数字。 指出前者返回标量,而后者返回0D数组。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

felixrehren picture felixrehren  ·  3评论

musm picture musm  ·  3评论

iamed2 picture iamed2  ·  3评论

Keno picture Keno  ·  3评论

manor picture manor  ·  3评论